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}
-
+
>
);
};
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;
+ }
+}