diff --git a/e2e/can-run-quiz.spec.ts b/e2e/can-run-quiz.spec.ts index eec39d77b..6fd075a5a 100644 --- a/e2e/can-run-quiz.spec.ts +++ b/e2e/can-run-quiz.spec.ts @@ -63,19 +63,18 @@ test("question page should contain 4 options and `submit` button", async ({ await page.getByRole("button", { name: "Submit", exact: true }).click(); }); -test("selected option must have 'answers-btns--selected' class", async ({ - page -}) => { +test("selected first option must be checked", async ({ page }) => { await page.getByRole("button", { name: "HTML" }).click(); await page.getByRole("button", { name: "10", exact: true }).click(); + const firstOptionText = await page.getByRole("button").first().textContent(); // Select the first option (no matter if it's right or wrong) await page.getByRole("button").first().click(); - await expect(page.getByRole("button").first()).toHaveClass( - /answers-btns--selected/ - ); + // Check if the first radio is checked + const hiddenRadioButton = page.locator(`input[id='${firstOptionText}']`); + await expect(hiddenRadioButton).toBeChecked(); }); test("should show a modal after selecting one option and click the `submit` button", async ({ diff --git a/e2e/score-and-results.spec.ts b/e2e/score-and-results.spec.ts index 567470937..bb1360554 100644 --- a/e2e/score-and-results.spec.ts +++ b/e2e/score-and-results.spec.ts @@ -68,7 +68,7 @@ test("should show 'success' modal after selecting the correct option", async ({ const questionData = await getQuestionData(question || ""); const answer = questionData.Answer; - await page.getByRole("button", { name: answer }).click(); + await page.getByRole("button", { name: answer, exact: true }).click(); await page.getByRole("button", { name: "Submit", exact: true }).click(); await verifyModalResponse(page, correctModalResponses, "1"); diff --git a/src/__tests__/Selectable.test.tsx b/src/__tests__/Selectable.test.tsx new file mode 100644 index 000000000..feb1355c4 --- /dev/null +++ b/src/__tests__/Selectable.test.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import Selectable from "../components/Selectable"; + +import { render, cleanup } from "@testing-library/react"; +import { vi } from "vitest"; +import { expect, afterEach, describe, it } from "vitest"; + +afterEach(cleanup); +describe("Selectable", () => { + it("Displays the passed options", () => { + const ops = ["one", "two", "three"]; + const { getByLabelText } = render( + + ); + expect(getByLabelText("one").textContent).toBeDefined(); + expect(getByLabelText("two").textContent).toBeDefined(); + expect(getByLabelText("three").textContent).toBeDefined(); + }); +}); diff --git a/src/components/Selectable.tsx b/src/components/Selectable.tsx new file mode 100644 index 000000000..0a9542cc0 --- /dev/null +++ b/src/components/Selectable.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import "../stylesheets/Selectable.css"; +const Selectable = ({ + options, + groupName, + onChange +}: { + options: string[]; + groupName: string; + onChange: (val: string) => void; +}) => { + return ( + + ); +}; +export default Selectable; diff --git a/src/constants.ts b/src/constants.ts index 79bea4874..298164862 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -31,7 +31,8 @@ export const CATEGORIES = [ "IT", "Linux", "Python", - "SQL" + "SQL", + "Random" ]; export const ALL_CATEGORIES = [ diff --git a/src/pages/Questions.tsx b/src/pages/Questions.tsx index 23ee2baab..0d862b76f 100644 --- a/src/pages/Questions.tsx +++ b/src/pages/Questions.tsx @@ -3,6 +3,7 @@ import QuizModal from "../components/QuizModal"; import React, { useEffect } from "react"; import { QuizProps } from "../types"; +import Selectable from "../components/Selectable"; const Questions: React.FC = QuizProps => { const navigate = useNavigate(); @@ -20,43 +21,41 @@ const Questions: React.FC = QuizProps => {

Points: {QuizProps.points}

Question {QuizProps.questionNumber}

-
+
{QuizProps.chooseAnswer ? ( ) : ( -
- - - Question {QuizProps.questionNumber} - - {QuizProps.currQuestion.Question} - -
    - {QuizProps.choicesArr.length > 0 && - QuizProps.choicesArr[QuizProps.questionNumber - 1].map( - (choice: string, index: number) => ( -
  • - -
  • - ) - )} -
-
- -
+ <> +
+ + + Question {QuizProps.questionNumber} + + {QuizProps.currQuestion.Question} + +
+ + { + QuizProps.selectOption(choice); + }} + /> + +
+
+ +
+ )} -
+ ); }; diff --git a/src/pages/SelectCategory.tsx b/src/pages/SelectCategory.tsx index bd7597c8e..662ef2b98 100644 --- a/src/pages/SelectCategory.tsx +++ b/src/pages/SelectCategory.tsx @@ -1,28 +1,21 @@ import React from "react"; import { CATEGORIES } from "../constants"; import { SelectCategoryProps } from "../types"; +import Selectable from "../components/Selectable"; const SelectCategory: React.FC = SelectCategoryProps => { return (

Choose a Category

-
- {CATEGORIES.map((category: string, index: number) => ( - - ))} - -
+ + category === "Random" + ? SelectCategoryProps.startRandomQuiz() + : SelectCategoryProps.selectQuiz(category, 0) + } + />
); }; diff --git a/src/pages/SelectQuestionsTotal.tsx b/src/pages/SelectQuestionsTotal.tsx index c2ea384b6..0ee6a5314 100644 --- a/src/pages/SelectQuestionsTotal.tsx +++ b/src/pages/SelectQuestionsTotal.tsx @@ -1,6 +1,7 @@ import React from "react"; import { QUESTION_NUMS } from "../constants"; import { SelectQuestionsTotalProps } from "../types"; +import Selectable from "../components/Selectable"; const SelectQuestionsTotal: React.FC = ({ totalQuestions, @@ -9,28 +10,23 @@ const SelectQuestionsTotal: React.FC = ({ const availableQuizLengths = QUESTION_NUMS.filter( length => length <= totalQuestions ); + const ops: string[] = [ + ...availableQuizLengths.map(n => `${n}`), // convert list of nums to list of strings + `All (${totalQuestions})` // add "all" option + ]; return (

Choose a length for the Quiz

-
- {availableQuizLengths.map((choice: number, index: number) => ( - - ))} - -
+ { + const num_choice = Number(choice.replace(/\D/g, "")); // handle "All (120) case" + startQuiz(num_choice); + }} + />
); }; diff --git a/src/stylesheets/App.css b/src/stylesheets/App.css index 0a83f228d..563129255 100644 --- a/src/stylesheets/App.css +++ b/src/stylesheets/App.css @@ -159,7 +159,7 @@ hr { @media screen and (min-width: 768px) { .select-btn-div { - width: 25%; + width: 50%; padding: 0; } } diff --git a/src/stylesheets/Selectable.css b/src/stylesheets/Selectable.css new file mode 100644 index 000000000..4506bfe7f --- /dev/null +++ b/src/stylesheets/Selectable.css @@ -0,0 +1,14 @@ +label:has(input[type="radio"]:checked) { + background-color: var(--bg-answer-selected); +} +ul, +li { + list-style-type: none; + input[type="radio"] { + display: none; + } + label { + color: var(--bg-primary); + text-align: center; + } +}