From 51801138b7dde474716191075e6c75668eae0361 Mon Sep 17 00:00:00 2001 From: bhnuka <01bhanukaekanayake@gmail.com> Date: Thu, 7 Nov 2024 10:44:58 +0800 Subject: [PATCH 1/5] testcase table --- .../question-service/src/models/Testcase.ts | 19 +++++++ .../src/routes/testcaseRoutes.ts | 20 +++++++ .../backend/question-service/src/server.ts | 3 ++ peerprep/frontend/src/api/testcaseApi.ts | 22 ++++++++ peerprep/frontend/src/styles/App.css | 8 ++- .../CollabServiceIntegratedView.tsx | 54 +++++++++++++++++-- 6 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 peerprep/backend/question-service/src/models/Testcase.ts create mode 100644 peerprep/backend/question-service/src/routes/testcaseRoutes.ts create mode 100644 peerprep/frontend/src/api/testcaseApi.ts diff --git a/peerprep/backend/question-service/src/models/Testcase.ts b/peerprep/backend/question-service/src/models/Testcase.ts new file mode 100644 index 0000000000..19cbf2e62a --- /dev/null +++ b/peerprep/backend/question-service/src/models/Testcase.ts @@ -0,0 +1,19 @@ +import mongoose, { Document, Schema } from 'mongoose'; + +export interface ITestcase extends Document { + questionId: number; + input1: string; + output1: string; + input2: string; + output2: string; +} + +const TestcaseSchema: Schema = new Schema({ + questionId: { type: Number, unique: true }, + input1: { type: String, required: true }, + output1: { type: String, required: true }, + input2: { type: String, required: true }, + output2: { type: String, required: true }, +}); + +export default mongoose.model('Testcase', TestcaseSchema); diff --git a/peerprep/backend/question-service/src/routes/testcaseRoutes.ts b/peerprep/backend/question-service/src/routes/testcaseRoutes.ts new file mode 100644 index 0000000000..e6e6a1990f --- /dev/null +++ b/peerprep/backend/question-service/src/routes/testcaseRoutes.ts @@ -0,0 +1,20 @@ +import express, { Request, Response } from 'express'; +import Testcase, { ITestcase } from '../models/Testcase'; + +const router = express.Router(); + +router.get('/testcases/:questionId', async (req: Request, res: Response) => { + const { questionId } = req.params; + try { + const testcase: ITestcase | null = await Testcase.findOne({ questionId }); + if (!testcase) { + return res.status(404).json({ message: 'Testcases not found' }); + } + res.json(testcase); + } catch (error) { + console.error('Error fetching testcases:', error); + res.status(500).json({ message: 'Server error' }); + } +}); + +export default router; diff --git a/peerprep/backend/question-service/src/server.ts b/peerprep/backend/question-service/src/server.ts index 3ed070789b..c8155d59d8 100644 --- a/peerprep/backend/question-service/src/server.ts +++ b/peerprep/backend/question-service/src/server.ts @@ -7,6 +7,7 @@ import connectDB from '../config/db'; import questionRoutes from './routes/questionRoutes'; import databaseRoutes from './routes/databaseRoutes'; import gptRoutes from './routes/gptRoutes'; +import testcaseRoutes from './routes/testcaseRoutes'; import loadSampleData from './sampleData'; connectDB() // Initialize MongoDB connection @@ -51,6 +52,8 @@ app.use('/api', databaseRoutes); app.use('/api', gptRoutes); +app.use('/api', testcaseRoutes); + // Health check route app.get('/hello', (req, res) => { res.json({ message: 'Hello World' }); diff --git a/peerprep/frontend/src/api/testcaseApi.ts b/peerprep/frontend/src/api/testcaseApi.ts new file mode 100644 index 0000000000..ced3e73ab4 --- /dev/null +++ b/peerprep/frontend/src/api/testcaseApi.ts @@ -0,0 +1,22 @@ +import axios from 'axios'; + +const API_URL = 'http://localhost:8080/api/testcases'; + +export interface Testcase { + questionId: number; + input1: string; + output1: string; + input2: string; + output2: string; +} + +export const getTestcasesByQuestionId = async (questionId: number): Promise => { + try { + const response = await axios.get(`${API_URL}/${questionId}`); + console.log('Fetched testcases:', response.data); + return response.data; + } catch (error) { + console.error('Error fetching testcases:', error); + throw error; + } +}; diff --git a/peerprep/frontend/src/styles/App.css b/peerprep/frontend/src/styles/App.css index 306cb0b92a..4724d69d20 100644 --- a/peerprep/frontend/src/styles/App.css +++ b/peerprep/frontend/src/styles/App.css @@ -518,7 +518,8 @@ h2 { width: 100%; height: 100%; max-width: 900px; - min-height: 300px; + max-height: 50px; + min-height: 50px; flex-grow: 1; position: relative; } @@ -527,7 +528,8 @@ h2 { width: 70%; height: 100%; max-width: 900px; - min-height: 300px; + max-height: 50px; + min-height: 50px; flex-grow: 1; border: 2px solid #ccc; border-radius: 10px; @@ -546,6 +548,8 @@ h2 { display: flex; flex-direction: column; height: 100%; + max-height: 200px; + min-height: 100px; border: 2px solid #ccc; border-radius: 10px; box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); diff --git a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx index 8032759d3a..c207853777 100644 --- a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx +++ b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx @@ -24,7 +24,7 @@ import { WebsocketProvider } from 'y-websocket'; import { deleteMatchedSession} from "../../api/matchingApi.ts"; import { getQuestionById } from '../../api/questionApi.ts'; - +import { getTestcasesByQuestionId, Testcase } from '../../api/testcaseApi.ts'; const CollaborationServiceIntegratedView: React.FC = () => { const { sessionId } = useParams<{ sessionId: string; }>(); @@ -36,6 +36,7 @@ const CollaborationServiceIntegratedView: React.FC = () => { const navigate = useNavigate(); const [yText, setYText] = useState(null); const [commentoutput, setCommentOutput] = useState(null); + const [testcases, setTestcases] = useState(null); console.log(commentoutput); //let topic = 'topic'; //let difficulty = 'difficulty'; @@ -45,6 +46,7 @@ const CollaborationServiceIntegratedView: React.FC = () => { const [difficulty, setDifficulty] = useState('N/A'); const [questionTitle, setQuestionTitle] = useState('N/A'); const [questionDescription, setQuestionDescription] = useState('N/A'); + const [questionId2, setQuestionId] = useState(0); console.log(sessionId); const questionId = sessionId ? sessionId.split('-Q')[1] : "N/A"; @@ -62,6 +64,7 @@ const CollaborationServiceIntegratedView: React.FC = () => { setDifficulty(response.difficulty); // Set difficulty from API response setQuestionTitle(response.title); setQuestionDescription(response.description); + setQuestionId(response.questionId); } } catch (error) { console.error('Error fetching matched session:', error); @@ -101,6 +104,24 @@ const CollaborationServiceIntegratedView: React.FC = () => { } }, [sessionId]); + useEffect(() => { + const fetchTestcases = async () => { + try { + const response2 = await getTestcasesByQuestionId(questionId2); + if (response2) { + console.log('Setting fetched testcases:', response2); + setTestcases(response2); + } + } catch (error) { + console.error('Error fetching testcases:', error); + } + }; + if (questionId2 && questionId2 !== 0) { + fetchTestcases(); + } + }, [questionId2]); + + const handleLeaveSession = () => { // Call the API to delete the session try { @@ -213,6 +234,7 @@ const CollaborationServiceIntegratedView: React.FC = () => {

Topics: {topics} | Difficulty: {difficulty}

Question: {questionTitle}

Description: {questionDescription}

+

Question ID: {questionId2}

@@ -301,9 +323,33 @@ const CollaborationServiceIntegratedView: React.FC = () => {
{/*
{commentoutput}
-
*/} - - ); + */} + + {testcases && ( +
+

Test Cases

+ + + + + + + + + + + + + + + + + +
Input 1Output 1Input 2Output 2
{testcases.input1}{testcases.output1}{testcases.input2}{testcases.output2}
+
+ )} + + ); }; export default CollaborationServiceIntegratedView; From 63142793140f74a572639c08e1bb73b09542a582 Mon Sep 17 00:00:00 2001 From: bhnuka <01bhanukaekanayake@gmail.com> Date: Thu, 7 Nov 2024 11:16:06 +0800 Subject: [PATCH 2/5] small css changes --- peerprep/frontend/src/styles/App.css | 37 ++++++++++++-- .../CollabServiceIntegratedView.tsx | 50 +++++++++---------- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/peerprep/frontend/src/styles/App.css b/peerprep/frontend/src/styles/App.css index 4724d69d20..0e02d70e3a 100644 --- a/peerprep/frontend/src/styles/App.css +++ b/peerprep/frontend/src/styles/App.css @@ -503,6 +503,7 @@ h2 { height: 85vh; /* Full height of the viewport */ width: 80vw; /* Full width of the viewport */ + overflow-y: auto; background-color: white; padding: 20px; box-sizing: border-box; /* Include padding in width and height calculations */ @@ -518,8 +519,8 @@ h2 { width: 100%; height: 100%; max-width: 900px; - max-height: 50px; - min-height: 50px; + max-height: 200px; + min-height: 200px; flex-grow: 1; position: relative; } @@ -528,8 +529,8 @@ h2 { width: 70%; height: 100%; max-width: 900px; - max-height: 50px; - min-height: 50px; + max-height: 200px; + min-height: 200px; flex-grow: 1; border: 2px solid #ccc; border-radius: 10px; @@ -777,4 +778,30 @@ input { .output-container{ overflow-y: scroll; -} \ No newline at end of file +} + +.testcases-table { + margin: 20px 0; + width: 100%; +} + +.testcases-table table { + width: 100%; + border-collapse: collapse; + border: 2px solid #333 !important; /* Outer border around the table */ + text-align: center; +} + +.testcases-table th, .testcases-table td { + border: 1px solid #333 !important; /* Border around each cell */ + padding: 8px; +} + +.testcases-table th { + background-color: #f2f2f2; + font-weight: bold; +} + +.testcases-table td { + background-color: #fff; +} diff --git a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx index c207853777..4e0e554fde 100644 --- a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx +++ b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx @@ -231,10 +231,8 @@ const CollaborationServiceIntegratedView: React.FC = () => {

Collaboration Session

-

Topics: {topics} | Difficulty: {difficulty}

-

Question: {questionTitle}

+

Topics: {topics} | Difficulty: {difficulty} | Question: {questionTitle}

Description: {questionDescription}

-

Question ID: {questionId2}

@@ -325,29 +323,29 @@ const CollaborationServiceIntegratedView: React.FC = () => {
{commentoutput}
*/} - {testcases && ( -
-

Test Cases

- - - - - - - - - - - - - - - - - -
Input 1Output 1Input 2Output 2
{testcases.input1}{testcases.output1}{testcases.input2}{testcases.output2}
-
- )} +{testcases && ( +
+

Test Cases

+ + + + + + + + + + + + + + + + + +
Input 1Output 1Input 2Output 2
{testcases.input1}{testcases.output1}{testcases.input2}{testcases.output2}
+
+)}
); }; From e7753587b09cdcd5470e5a8cd7173cbb28eb81fb Mon Sep 17 00:00:00 2001 From: bhnuka <01bhanukaekanayake@gmail.com> Date: Thu, 7 Nov 2024 12:02:59 +0800 Subject: [PATCH 3/5] update naming for consistency --- .../src/models/{Testcase.ts => testcaseModel.ts} | 0 peerprep/backend/question-service/src/routes/testcaseRoutes.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename peerprep/backend/question-service/src/models/{Testcase.ts => testcaseModel.ts} (100%) diff --git a/peerprep/backend/question-service/src/models/Testcase.ts b/peerprep/backend/question-service/src/models/testcaseModel.ts similarity index 100% rename from peerprep/backend/question-service/src/models/Testcase.ts rename to peerprep/backend/question-service/src/models/testcaseModel.ts diff --git a/peerprep/backend/question-service/src/routes/testcaseRoutes.ts b/peerprep/backend/question-service/src/routes/testcaseRoutes.ts index e6e6a1990f..239a4d0904 100644 --- a/peerprep/backend/question-service/src/routes/testcaseRoutes.ts +++ b/peerprep/backend/question-service/src/routes/testcaseRoutes.ts @@ -1,5 +1,5 @@ import express, { Request, Response } from 'express'; -import Testcase, { ITestcase } from '../models/Testcase'; +import Testcase, { ITestcase } from '../models/testcaseModel'; const router = express.Router(); From cae58f9a71a985239d48fb41d021ff76dda9735d Mon Sep 17 00:00:00 2001 From: bhnuka <01bhanukaekanayake@gmail.com> Date: Fri, 8 Nov 2024 00:47:10 +0800 Subject: [PATCH 4/5] update to use title coz qn id changes everytime but title doesnt. also, add error handling for no testcase found --- .../src/models/testcaseModel.ts | 2 + .../src/routes/testcaseRoutes.ts | 6 +-- .../question-service/src/sampleData.ts | 14 +----- peerprep/frontend/src/api/testcaseApi.ts | 5 +- .../CollabServiceIntegratedView.tsx | 47 ++++++++++++++----- 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/peerprep/backend/question-service/src/models/testcaseModel.ts b/peerprep/backend/question-service/src/models/testcaseModel.ts index 19cbf2e62a..43187838d5 100644 --- a/peerprep/backend/question-service/src/models/testcaseModel.ts +++ b/peerprep/backend/question-service/src/models/testcaseModel.ts @@ -2,6 +2,7 @@ import mongoose, { Document, Schema } from 'mongoose'; export interface ITestcase extends Document { questionId: number; + title: string; input1: string; output1: string; input2: string; @@ -10,6 +11,7 @@ export interface ITestcase extends Document { const TestcaseSchema: Schema = new Schema({ questionId: { type: Number, unique: true }, + title: { type: String, unique: true }, input1: { type: String, required: true }, output1: { type: String, required: true }, input2: { type: String, required: true }, diff --git a/peerprep/backend/question-service/src/routes/testcaseRoutes.ts b/peerprep/backend/question-service/src/routes/testcaseRoutes.ts index 239a4d0904..b9c179c3d6 100644 --- a/peerprep/backend/question-service/src/routes/testcaseRoutes.ts +++ b/peerprep/backend/question-service/src/routes/testcaseRoutes.ts @@ -3,10 +3,10 @@ import Testcase, { ITestcase } from '../models/testcaseModel'; const router = express.Router(); -router.get('/testcases/:questionId', async (req: Request, res: Response) => { - const { questionId } = req.params; +router.get('/testcases/:title', async (req: Request, res: Response) => { + const { title } = req.params; try { - const testcase: ITestcase | null = await Testcase.findOne({ questionId }); + const testcase: ITestcase | null = await Testcase.findOne({ title }); if (!testcase) { return res.status(404).json({ message: 'Testcases not found' }); } diff --git a/peerprep/backend/question-service/src/sampleData.ts b/peerprep/backend/question-service/src/sampleData.ts index 046c68cea0..14a59d7fd7 100644 --- a/peerprep/backend/question-service/src/sampleData.ts +++ b/peerprep/backend/question-service/src/sampleData.ts @@ -104,12 +104,6 @@ const sampleQuestions = [ categories: 'Data Structures, Algorithms', difficulty: 'medium', }, - { - title: 'LRU Cache Design', - description: `Design and implement an LRU (Least Recently Used) cache.`, - categories: 'Data Structures', - difficulty: 'medium', - }, { title: 'Longest Common Subsequence', description: `Given two strings text1 and text2, return the length of their longest common subsequence. If there is no common subsequence, return 0. @@ -141,13 +135,7 @@ const sampleQuestions = [ description: `Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection. Design an algorithm to serialize and deserialize a binary tree.`, categories: 'Data Structures, Algorithms', difficulty: 'hard', - }, - { - title: 'Trips and Users', - description: `Given table Trips with columns id, client_id, driver_id, city_id, status, request_at, and table Users with columns users_id, banned, role, write a solution to find the cancellation rate of requests with unbanned users (both client and driver must not be banned) between specific dates.`, - categories: 'Databases', - difficulty: 'hard', - }, + } ]; // Create a helper function to simulate the Express request-response cycle diff --git a/peerprep/frontend/src/api/testcaseApi.ts b/peerprep/frontend/src/api/testcaseApi.ts index ced3e73ab4..6a60381d06 100644 --- a/peerprep/frontend/src/api/testcaseApi.ts +++ b/peerprep/frontend/src/api/testcaseApi.ts @@ -4,15 +4,16 @@ const API_URL = 'http://localhost:8080/api/testcases'; export interface Testcase { questionId: number; + title: string; input1: string; output1: string; input2: string; output2: string; } -export const getTestcasesByQuestionId = async (questionId: number): Promise => { +export const getTestcasesByTitle = async (title: string): Promise => { try { - const response = await axios.get(`${API_URL}/${questionId}`); + const response = await axios.get(`${API_URL}/${title}`); console.log('Fetched testcases:', response.data); return response.data; } catch (error) { diff --git a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx index 4e0e554fde..97b9e0eb2f 100644 --- a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx +++ b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx @@ -24,7 +24,7 @@ import { WebsocketProvider } from 'y-websocket'; import { deleteMatchedSession} from "../../api/matchingApi.ts"; import { getQuestionById } from '../../api/questionApi.ts'; -import { getTestcasesByQuestionId, Testcase } from '../../api/testcaseApi.ts'; +import { getTestcasesByTitle, Testcase } from '../../api/testcaseApi.ts'; const CollaborationServiceIntegratedView: React.FC = () => { const { sessionId } = useParams<{ sessionId: string; }>(); @@ -36,7 +36,15 @@ const CollaborationServiceIntegratedView: React.FC = () => { const navigate = useNavigate(); const [yText, setYText] = useState(null); const [commentoutput, setCommentOutput] = useState(null); - const [testcases, setTestcases] = useState(null); + const [testcases, setTestcases] = useState({ + questionId: 0, + title: "N/A", + input1: "N/A", + output1: "N/A", + input2: "N/A", + output2: "N/A" + }); + console.log(commentoutput); //let topic = 'topic'; //let difficulty = 'difficulty'; @@ -46,7 +54,6 @@ const CollaborationServiceIntegratedView: React.FC = () => { const [difficulty, setDifficulty] = useState('N/A'); const [questionTitle, setQuestionTitle] = useState('N/A'); const [questionDescription, setQuestionDescription] = useState('N/A'); - const [questionId2, setQuestionId] = useState(0); console.log(sessionId); const questionId = sessionId ? sessionId.split('-Q')[1] : "N/A"; @@ -64,7 +71,6 @@ const CollaborationServiceIntegratedView: React.FC = () => { setDifficulty(response.difficulty); // Set difficulty from API response setQuestionTitle(response.title); setQuestionDescription(response.description); - setQuestionId(response.questionId); } } catch (error) { console.error('Error fetching matched session:', error); @@ -77,7 +83,6 @@ const CollaborationServiceIntegratedView: React.FC = () => { useEffect(() => { console.log(`Session ID: ${sessionId}, Topics: ${topics}, Difficulty: ${difficulty}`); - console.log(`Question: ${questionId}`); }, [sessionId, topics, difficulty, questionId]); useEffect(() => { @@ -107,19 +112,39 @@ const CollaborationServiceIntegratedView: React.FC = () => { useEffect(() => { const fetchTestcases = async () => { try { - const response2 = await getTestcasesByQuestionId(questionId2); - if (response2) { - console.log('Setting fetched testcases:', response2); - setTestcases(response2); + const response = await getTestcasesByTitle(questionTitle); + if (response) { + console.log('Setting fetched testcases:', response); + setTestcases(response); + } else { + console.log('No testcases found, setting default values'); + setTestcases({ + questionId: 0, + title: "N/A", + input1: "N/A", + output1: "N/A", + input2: "N/A", + output2: "N/A" + }); } } catch (error) { console.error('Error fetching testcases:', error); + setTestcases({ + questionId: 0, + title: "N/A", + input1: "N/A", + output1: "N/A", + input2: "N/A", + output2: "N/A" + }); } }; - if (questionId2 && questionId2 !== 0) { + + if (questionTitle && questionTitle !== 'N/A') { fetchTestcases(); } - }, [questionId2]); + }, [questionTitle]); + const handleLeaveSession = () => { From 434b107f86e9144c54498d88f5474843726c0dda Mon Sep 17 00:00:00 2001 From: bhnuka <01bhanukaekanayake@gmail.com> Date: Sat, 9 Nov 2024 23:34:47 +0800 Subject: [PATCH 5/5] update styles so it works when shrunk and hides scroll bars --- peerprep/frontend/src/styles/App.css | 46 +++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/peerprep/frontend/src/styles/App.css b/peerprep/frontend/src/styles/App.css index 0e02d70e3a..25fbfdeb3d 100644 --- a/peerprep/frontend/src/styles/App.css +++ b/peerprep/frontend/src/styles/App.css @@ -22,7 +22,6 @@ h2 { color: black; } - /* Container uses flexbox for split layout */ .container { display: flex; @@ -503,10 +502,17 @@ h2 { height: 85vh; /* Full height of the viewport */ width: 80vw; /* Full width of the viewport */ - overflow-y: auto; + overflow-y: scroll; + overflow-x: hidden; background-color: white; padding: 20px; box-sizing: border-box; /* Include padding in width and height calculations */ + scrollbar-width: none; +} + +/* Hide scrollbar for Webkit browsers (Chrome, Safari) */ +.editor-container-parent::-webkit-scrollbar { + display: none; } .CodeMirror { @@ -544,6 +550,16 @@ h2 { vertical-align: top; /* Ensures text starts from the top */ } +/* Hide scrollbar for Webkit browsers (Chrome, Safari) */ +.editor-container::-webkit-scrollbar { + display: none; +} + +/* Hide scrollbar for Firefox */ +.editor-container { + scrollbar-width: none; /* Firefox */ +} + .chat-box { width: 30%; display: flex; @@ -628,7 +644,7 @@ input { .editor-header { text-align: center; margin-bottom: -10px; - margin-top: -60px; + margin-top: -45px; } .leave-btn, @@ -697,12 +713,13 @@ input { display: flex; flex-direction: row; /* Arrange items in a vertical stack */ align-items: center; /* Align items to the left */ - gap: 100px; /* Add vertical spacing between items */ + gap: 60px; /* Add vertical spacing between items */ } .matching-form2 { padding: 0px; max-width: 40%; + min-width: 18%; margin: 0 auto; /* Center the form */ border-radius: 10px; /* Rounded corners for the form */ background-color: white; @@ -778,20 +795,35 @@ input { .output-container{ overflow-y: scroll; + min-height: 50px; + max-height: 100px; + max-width: 900px; +} + +/* Hide scrollbar for Webkit browsers (Chrome, Safari) */ +.output-container::-webkit-scrollbar { + display: none; +} + +/* Hide scrollbar for Firefox */ +.output-container { + scrollbar-width: none; /* Firefox */ } .testcases-table { - margin: 20px 0; - width: 100%; + margin: 20px auto; /* Center the table horizontally */ + max-width: 900px; /* Set max width */ + width: 100%; /* Allow the table to expand to max-width */ } .testcases-table table { - width: 100%; border-collapse: collapse; border: 2px solid #333 !important; /* Outer border around the table */ text-align: center; + width: 100%; /* Ensure the table fills the container width */ } + .testcases-table th, .testcases-table td { border: 1px solid #333 !important; /* Border around each cell */ padding: 8px;