diff --git a/README.md b/README.md
index dc15a20d7093cddeffe23b4a6ba1208c93f46aa4..e8951d831fc8a1abefb7eb5a3319c69288bdd8ff 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,19 @@
 
 The frontend component of the Trivio quiz application is built using Vue.js and Vite. It provides a user interface for interacting with the backend APIs. Unit testing is performed using vitest, while integration testing is conducted using Cypress.
 
+## Content
+- [Functionality](#functionality)
+- [Security]("#security")
+- [Installation](#installation)
+- [Usage](#usage)
+- [Tests](#tests)
+- [Dependencies](#dependencies)
+- [Future work](#future-work)
+- [Authors](#authors)
+# Frontend Trivio
+
+The frontend component of the Trivio quiz application is built using Vue.js and Vite. It provides a user interface for interacting with the backend APIs. Unit testing is performed using vitest, while integration testing is conducted using Cypress.
+
 ## Content
 - [Functionality](#functionality)
 - [Security]("#security")
@@ -44,6 +57,42 @@ git clone https://gitlab.stud.idi.ntnu.no/team_fullastack/frontend_fullstack.git
 cd frontend_fullstack
 ```
 
+4. Install dependencies:
+```bash
+npm install
+```
+## Functionality
+User
+- Sign in and log in
+- Discover quizzes made by other users
+- Take quizzes
+- Get score after quiz 
+- Watch previous quiz scores
+- Make a quiz
+- Collaborate on quizzes
+- Contact admin 
+- Change username and password
+
+Admin 
+- Access to all users
+- See all trivios 
+
+## Security
+Trivio uses JWT-Tokens for user authentication during API calls. Upon user login, the backend validates the provided email and encoded password comparing them with existing user records. A JTO token is generated using JWTSBuilder, incorporating the user's id and expiration time. This token serves as the user's authentication credential for making API calls. 
+
+## Installation
+1. Make sure you have Node.js and npm installed
+
+2. Clone the repository 
+```bash 
+git clone https://gitlab.stud.idi.ntnu.no/team_fullastack/frontend_fullstack.git
+```
+
+3. Navigate to frontend_fullstack:
+```bash
+cd frontend_fullstack
+```
+
 4. Install dependencies:
 ```bash
 npm install
@@ -60,6 +109,20 @@ This will start the application locally and display the URL where it can be acce
 
 ## Tests
 
+### Cypress
+1. Ensure that both the backend and frontend applications are running.
+
+2. Run Cypress interaction tests:
+```bash
+npm run test:e2e
+```
+
+### Vitest 
+1. Run Vitest unit tests:
+```bash
+npm run test:unit
+```
+
 ## Dependencies
 - Vue.js
 - Vite
@@ -71,6 +134,15 @@ This will start the application locally and display the URL where it can be acce
 
 ## Future work
 
+### Mobile Responsive UI
+Implement a mobile-friendly user interface to ensure optimal user experience across various devices and screen sizes. This involves optimizing layouts, font sizes, and interactive elements for smaller screens.
+
+### Additional Admin Functionalities
+Expand the capabilities of the admin dashboard to provide more control and management options.
+
+### Performance 
+As the project developed, we adjusted our functionalities to meet requirements and time constraints. Consequently, some aspects of our database queries and server-side logic may not be optimized for performance. To enhance the efficiency of our application, future work will prioritize optimizing these areas, resulting in improved server-side performance.
+
 ## Authors
 Gia Hy Nguyen  
 Tini Tran  
diff --git a/cypress.config.ts b/cypress.config.ts
index 0f66080fd0637080f5e2f5151146e89797be2e54..f80530a2a66e24534ac18223b7603fd3d0206f49 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -3,6 +3,6 @@ import { defineConfig } from 'cypress'
 export default defineConfig({
   e2e: {
     specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
-    baseUrl: 'http://localhost:4173'
+    baseUrl: 'http://localhost:5173'
   }
 })
diff --git a/cypress/e2e/example.cy.ts b/cypress/e2e/example.cy.ts
deleted file mode 100644
index 7554c35d8d0ff1412457a5ae7f8649a9871cc21b..0000000000000000000000000000000000000000
--- a/cypress/e2e/example.cy.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// https://on.cypress.io/api
-
-describe('My First Test', () => {
-  it('visits the app root url', () => {
-    cy.visit('/')
-    cy.contains('h1', 'You did it!')
-  })
-})
diff --git a/cypress/e2e/frontpage/login.cy.ts b/cypress/e2e/frontpage/login.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..754f077603a66e9dad23cbdbee3b8faca98699db
--- /dev/null
+++ b/cypress/e2e/frontpage/login.cy.ts
@@ -0,0 +1,29 @@
+describe('Login Form', () => {
+  beforeEach(() => {
+    cy.visit('/') 
+  })
+
+  it('should log in with valid credentials', () => {
+    // Enter valid username and password
+    cy.get('#username').type('test')
+    cy.get('#password').type('password')
+
+    // Click the login button
+    cy.get('#signinButton').click()
+
+    // Ensure redirected to the homepage or appropriate route after successful login
+    cy.url().should('include', '/homepage') 
+  })
+
+  it('should display error message with invalid password', () => {
+    // Enter password
+    cy.get('#username').type('test')
+    cy.get('#password').type('pass')
+
+    // Click the login button
+    cy.get('#signinButton').click()
+
+    // Check if error message is displayed
+    cy.get('#loginStatus').should('have.text', 'Login failed')
+  })
+})
\ No newline at end of file
diff --git a/cypress/e2e/frontpage/signup.cy.ts b/cypress/e2e/frontpage/signup.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..806dc785dbbe466d0b50617deb85852d7064d6cf
--- /dev/null
+++ b/cypress/e2e/frontpage/signup.cy.ts
@@ -0,0 +1,56 @@
+describe('Create Account Form', () => {
+    beforeEach(() => {
+      cy.visit('/createAccount')
+    })
+  
+    it('should sign in with valid credentials', () => {
+      // Enter valid username and password
+      cy.get('#username').type('account')
+      cy.get('#password').type('password')
+      cy.get('#email').type('account@mail.com')
+  
+      // Click the sign-in button
+      cy.get('#signinButton').click()
+  
+      // Ensure redirected to the dashboard or appropriate route after successful sign-in
+      cy.url().should('include', '/homepage') 
+    })
+  
+    it('should display error message with invalid email', () => {
+      // Enter valid username and password, but invalid email
+      cy.get('#username').type('username')
+      cy.get('#password').type('password')
+      cy.get('#email').type('InvalidEmail')
+  
+      // Click the sign-in button
+      cy.get('#signinButton').click()
+  
+      // Check if error message is displayed
+      cy.get('#loginStatus').should('have.text', 'Please enter a valid email address')
+    })
+
+    it('should display error message when username is empty', () => {
+      // Enter empty username
+      cy.get('#password').type('password')
+      cy.get('#email').type('username@mail.com')
+  
+      // Click the sign-in button
+      cy.get('#signinButton').click()
+  
+      // Check if error message is displayed
+      cy.get('#loginStatus').should('have.text', 'Please enter a username')
+    })
+
+    it('should display error message when password is empty', () => {
+      // Enter empty password
+      cy.get('#username').type('username')
+      cy.get('#email').type('username@mail.com')
+
+      // Click the sign-in button
+      cy.get('#signinButton').click()
+
+      // Check if error message is displayed
+      cy.get('#loginStatus').should('have.text', 'Please enter a password')
+    })
+  })
+  
\ No newline at end of file
diff --git a/cypress/e2e/mainpage/contact.cy.ts b/cypress/e2e/mainpage/contact.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3e6960c8c9eef2e562e753df12e34eda73d49fa0
--- /dev/null
+++ b/cypress/e2e/mainpage/contact.cy.ts
@@ -0,0 +1,39 @@
+describe('Contact Form', () => {
+    beforeEach(() => {
+        cy.login('test', 'password')
+        cy.visit('/homepage/contact')
+    })
+
+    it('should submit the form with valid input', () => {
+        // Fill in the form fields
+        cy.get('#name').type('John Doe');
+        cy.get('#email').type('john.doe@example.com');
+        cy.get('#message').type('This is a test message');
+
+        // Submit the form
+        cy.get('#submit_button').click();
+
+        // Check for success message
+        cy.get('.response').should('contain.text', 'Message sent. Thanks for feedback!');
+    });
+
+    it('should display error message if email field is empty', () => {
+        // Submit the form without filling in the email field
+        cy.get('#name').type('John Doe');
+        cy.get('#message').type('This is a test message');
+        cy.get('#submit_button').click();
+
+        // Check for error message
+        cy.get('.response').should('contain.text', 'Email cannot be empty');
+    });
+
+    it('should display error message if message field is empty', () => {
+        // Submit the form without filling in the message field
+        cy.get('#name').type('John Doe');
+        cy.get('#email').type('john.doe@example.com');
+        cy.get('#submit_button').click();
+
+        // Check for error message
+        cy.get('.response').should('contain.text', 'Message cannot be empty');
+    });
+})
diff --git a/cypress/e2e/mainpage/discovery.cy.ts b/cypress/e2e/mainpage/discovery.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7e9a3519de7f69a95c5ee26a65014129ef539f0c
--- /dev/null
+++ b/cypress/e2e/mainpage/discovery.cy.ts
@@ -0,0 +1,72 @@
+describe('Discovery View', () => {
+    beforeEach(() => {
+        cy.login('test', 'password') 
+    })
+
+    it('should display trivios', () => {
+        // Check if card container exists
+        cy.get('.card-container').should('exist')
+
+        // Check if at least one TrivioCard component is visible inside the card container
+        cy.get('.card-container .box', { timeout: 5000 }).should('exist')
+    })
+
+    it('should display trivio with correct tags', () => {
+        // Click "Add Tag" button
+        cy.get('.addTag').click()
+
+        // Click the first tag input box and enter "Capital"
+        cy.get('.tag-box input').first().click().type('Capital')
+
+        // Press Enter after typing the first tag
+        cy.get('.tag-box input').first().type('{enter}')
+
+        // Check if at least one TrivioCard component is visible inside the card container
+        cy.get('.card-container .box', { timeout: 5000 }).should('exist')
+    })
+
+    it('should not display any trivio with incorrect tags', () => {
+        // Click "Add Tag" button
+        cy.get('.addTag').click()
+
+        // Click the first tag input box and enter "InvalidTag"
+        cy.get('.tag-box input').first().click().type('InvalidTag')
+
+        // Press Enter after typing the first tag
+        cy.get('.tag-box input').first().type('{enter}')
+
+        // Check if no TrivioCard component is visible inside the card container
+        cy.get('.card-container .box', { timeout: 5000 }).should('not.exist')
+    })
+
+
+    it('should display trivio with correct difficulty', () => {
+        // Select "Medium" in the Difficulty dropdown
+        cy.get('.FilterOptions select').eq(1).select('Easy')
+
+        // Assert that "Medium" is selected in the Difficulty dropdown
+        cy.get('.FilterOptions select').eq(1).should('have.value', 'Easy')
+
+        // Check if at least one TrivioCard component is visible inside the card container
+        cy.get('.card-container .box', { timeout: 5000 }).should('exist')
+    })
+
+    it('should display trivio with incorrect difficulty', () => {
+        // Select "Medium" in the Difficulty dropdown
+        cy.get('.FilterOptions select').eq(1).select('Medium')
+
+        // Assert that "Medium" is selected in the Difficulty dropdown
+        cy.get('.FilterOptions select').eq(1).should('have.value', 'Medium')
+
+        // Check if at least one TrivioCard component is visible inside the card container
+        cy.get('.card-container .box', { timeout: 5000 }).should('not.exist')
+    })
+
+    it('should navigate to start page when a TrivioCard is clicked', () => {
+        // Click on the first TrivioCard
+        cy.get('.card-container .box').first().click()
+
+        // Assert that the URL has changed to the expected route
+        cy.url().should('include', '/homepage/start')
+    })
+})
diff --git a/cypress/e2e/mainpage/editTrivios.cy.ts b/cypress/e2e/mainpage/editTrivios.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0a8c0fcb0447eba59449161978b493bc7695ec7f
--- /dev/null
+++ b/cypress/e2e/mainpage/editTrivios.cy.ts
@@ -0,0 +1,38 @@
+describe('EditTrivio Component', () => {
+    beforeEach(() => {
+        cy.login('test', 'password') 
+        cy.visit('/homepage/trivios')
+        cy.get('.card-container .box').first().click()
+        cy.get('.user-button-one').first().click()
+    })
+
+    it('should display the component with correct initial data', () => {
+        // Check if the component title is displayed
+        cy.contains('h1', 'Edit Trivio').should('exist')
+
+        // Check if the initial input fields are displayed
+        cy.get('.header').should('exist')
+        cy.get('.input-boxes').should('exist')
+        cy.get('.questions').should('exist')
+        cy.get('.add-box').should('exist')
+
+        // Check if the difficulty, category, and visibility dropdowns are displayed
+        cy.get('.option').should('have.length', 3)
+
+        // Check if the add question button is displayed
+        cy.get('.add-question').should('exist')
+    })
+
+    it('should appear correct alert message and route to start page when clicking save', () => {
+        // Click the save button
+        cy.get('.top-button').contains('Save').click()
+
+        // Check if the alert box is displayed with the correct message
+        cy.on('window:alert', (alertMessage) => {
+            expect(alertMessage).to.equal('Trivio Updated!')
+        })
+
+        // Ensure that the router navigates back to the start page after saving
+        cy.url().should('include', '/start') 
+    })
+})
diff --git a/cypress/e2e/mainpage/history.cy.ts b/cypress/e2e/mainpage/history.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..08cec4cc0233d8469bf00158016d07152412dbc7
--- /dev/null
+++ b/cypress/e2e/mainpage/history.cy.ts
@@ -0,0 +1,18 @@
+describe('History Page', () => {
+    beforeEach(() => {
+      cy.login('test', 'password')
+      cy.visit('/homepage/history') 
+    })
+  
+    it('should display history', () => {
+      // Check if history is displayed
+      cy.get('.History').should('be.visible')
+  
+      // Check if trivio titles are visible
+      cy.get('.filter select#titleFilter').should('be.visible')
+  
+      // Check if pagination buttons are visible
+      cy.get('.pagination button').should('be.visible')
+    })
+})
+  
\ No newline at end of file
diff --git a/cypress/e2e/mainpage/makeTrivio.cy.ts b/cypress/e2e/mainpage/makeTrivio.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0fc76e0397faa5d7bb63794b6b305c541c5689ff
--- /dev/null
+++ b/cypress/e2e/mainpage/makeTrivio.cy.ts
@@ -0,0 +1,42 @@
+describe('MakeTrivio Component', () => {
+    beforeEach(() => {
+        cy.login('test', 'password')
+        cy.visit('/homepage/create-trivio')
+    })
+
+    it('should display the component with correct initial data', () => {
+        // Check if the component title is displayed
+        cy.contains('h1', 'Create new quiz').should('exist')
+
+        // Check if the initial input fields are displayed
+        cy.get('.header').should('exist')
+        cy.get('.input-boxes').should('exist')
+        cy.get('.questions').should('exist')
+        cy.get('.add-box').should('exist')
+
+        // Check if the difficulty, category, and visibility dropdowns are displayed
+        cy.get('.option').should('have.length', 3)
+
+        // Check if the add question button is displayed
+        cy.get('.add-question').should('exist')
+    })
+
+    it('should add a question when the add question button is clicked', () => {
+        // Click the add question button
+        cy.get('.add-question').click()
+
+        // Check if the question input boxes are displayed
+        cy.get('.questions').should('have.length', 1)
+
+        // Check if the answer input boxes are displayed
+        cy.get('.answer').should('have.length', 4)
+    })
+    
+    it('should route to my trivios page when clicking create', () => {
+        // Click the save button
+        cy.get('.top-button').contains('Create').click()
+
+        // Ensure that the router navigates back to the start page after saving
+        cy.url().should('include', '/trivios')
+    })
+})
diff --git a/cypress/e2e/mainpage/myTrivios.cy.ts b/cypress/e2e/mainpage/myTrivios.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bd3363f6c8bf5860fbbae9ac9466b3bd6bc93a13
--- /dev/null
+++ b/cypress/e2e/mainpage/myTrivios.cy.ts
@@ -0,0 +1,27 @@
+describe('My Trivios Component', () => {
+    beforeEach(() => {
+        cy.login('test', 'password')
+        cy.visit('/homepage/trivios') 
+    })
+
+    it('should display the filter options', () => {
+        // Check if category and difficulty filter options are visible
+        cy.get('.FilterOptions').should('be.visible')
+        cy.get('.option').should('have.length', 4) 
+    })
+
+    it('should display the tags section', () => {
+        // Check if the tags section is visible
+        cy.get('.tag-section').should('be.visible')
+
+        // Check if the "Add Tag" button is visible
+        cy.contains('.addTag', 'Add Tag +').should('be.visible')
+    })
+
+    it('should display pagination', () => {
+        // Check if the pagination section is visible
+        cy.get('.pagination').should('be.visible')
+
+        cy.get('.pagination').find('button').should('exist')
+    })
+})
diff --git a/cypress/e2e/mainpage/profile.cy.ts b/cypress/e2e/mainpage/profile.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2cf0410fed3c338d1b5ef165c9a04c715aa87c12
--- /dev/null
+++ b/cypress/e2e/mainpage/profile.cy.ts
@@ -0,0 +1,25 @@
+describe('Profile Component', () => {
+    beforeEach(() => {
+        cy.login('test', 'password');
+        cy.visit('/homepage/profile');
+    });
+
+    it('fetches user information on mount', () => {
+        // Check if user information is displayed correctly
+        cy.get('#username').should('have.value', 'test');
+        cy.get('#email').should('have.value', 'username@mail.com');
+    });
+
+    it('should allow editing user information', () => {
+        // Type new username and email
+        cy.get('#username').clear().type('newUsername')
+        cy.get('#email').clear().type('newEmail@example.com')
+    
+        // Save changes
+        cy.get('.user-info-header .save-button').click()
+    
+        // Check if changes are saved
+        cy.get('#username').should('have.value', 'newUsername')
+        cy.get('#email').should('have.value', 'newEmail@example.com')
+      })
+});
diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts
index 9b7bb8e2584cf20c9f578c69dada5f6024b4b042..843daaee6a2de888289340586e8175ed0bb83c04 100644
--- a/cypress/support/commands.ts
+++ b/cypress/support/commands.ts
@@ -1,39 +1,23 @@
 /// <reference types="cypress" />
-// ***********************************************
-// This example commands.ts shows you how to
-// create various custom commands and overwrite
-// existing commands.
-//
-// For more comprehensive examples of custom
-// commands please read more here:
-// https://on.cypress.io/custom-commands
-// ***********************************************
-//
-//
-// -- This is a parent command --
-// Cypress.Commands.add('login', (email, password) => { ... })
-//
-//
-// -- This is a child command --
-// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
-//
-//
-// -- This is a dual command --
-// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
-//
-//
-// -- This will overwrite an existing command --
-// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
-//
-// declare global {
-//   namespace Cypress {
-//     interface Chainable {
-//       login(email: string, password: string): Chainable<void>
-//       drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
-//       dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
-//       visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
-//     }
-//   }
-// }
 
-export {}
+declare global {
+    namespace Cypress {
+        interface Chainable {
+            /**
+             * Custom command to log in.
+             * @example cy.login('username', 'password')
+             */
+            login(username: string, password: string): Chainable<void>;
+        }
+    }
+}
+
+Cypress.Commands.add('login', (username, password) => {
+    cy.visit('/login') // Adjust the URL as needed
+    cy.get('#username').type(username)
+    cy.get('#password').type(password)
+    cy.get('#signinButton').click()
+    cy.url().should('include', '/homepage')
+})
+
+export { }
diff --git a/package.json b/package.json
index d8f9c1c17ec11a2d96ca31afbd143866e5fafae3..7726d7324b2eb115decaf953c28da5662cbbbfad 100644
--- a/package.json
+++ b/package.json
@@ -8,8 +8,8 @@
     "build": "run-p type-check \"build-only {@}\" --",
     "preview": "vite preview",
     "test:unit": "vitest",
-    "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'",
-    "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'",
+    "test:e2e": "start-server-and-test preview http://localhost:5173 'cypress run --e2e'",
+    "test:e2e:dev": "start-server-and-test 'vite dev --port 5173' http://localhost:5173 'cypress open --e2e'",
     "build-only": "vite build",
     "type-check": "vue-tsc --build --force",
     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
diff --git a/src/components/__tests__/HelloWorld.spec.ts b/src/components/__tests__/HelloWorld.spec.ts
deleted file mode 100644
index 2533202008f7270910420c60a420efaf9b505c90..0000000000000000000000000000000000000000
--- a/src/components/__tests__/HelloWorld.spec.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { describe, it, expect } from 'vitest'
-
-import { mount } from '@vue/test-utils'
-import HelloWorld from '../HelloWorld.vue'
-
-describe('HelloWorld', () => {
-  it('renders properly', () => {
-    const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
-    expect(wrapper.text()).toContain('Hello Vitest')
-  })
-})
diff --git a/src/components/__tests__/HistoryBox.spec.ts b/src/components/__tests__/HistoryBox.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cf9a540b0ca2022988e667b222c5336cb8f8c41a
--- /dev/null
+++ b/src/components/__tests__/HistoryBox.spec.ts
@@ -0,0 +1,39 @@
+import { describe, it, expect } from 'vitest'
+
+import { mount } from '@vue/test-utils';
+import HistoryBox from '@/components/HistoryBox.vue';  
+
+describe('HistoryBox', () => {
+  it('renders with correct props', () => {
+    // Mock props
+    const props = {
+      title: 'Sample Quiz',
+      image: '/sample-image.png',
+      numberOfQuestion: 10,
+      username: 'John Doe',
+      difficulty: 'Easy',
+      score: 8,
+      date: '2024-04-10',
+    };
+
+    // Mount the component with mock props
+    const wrapper = mount(HistoryBox, {
+      props,
+    });
+
+    // Assert that the rendered component contains the correct information
+    expect(wrapper.find('.quiz-title').text()).toBe(props.title);
+    expect(wrapper.find('.difficulty').text()).toContain(`Difficulty: ${props.difficulty}`);
+    expect(wrapper.find('.username').text()).toBe(props.username);
+    expect(wrapper.find('.score-text').text()).toContain(`${props.score}/${props.numberOfQuestion}`);
+    expect(wrapper.find('.date').text()).toBe(props.date);
+    
+    // Assert image source
+    const imageSrc = wrapper.find('.quiz-box img').attributes('src');
+    if (props.image) {
+      expect(imageSrc).toBe(props.image);
+    } else {
+      expect(imageSrc).toBe('/src/assets/trivio.svg');
+    }
+  });
+});
diff --git a/src/components/__tests__/QuestionBox.spec.ts b/src/components/__tests__/QuestionBox.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ff17e65757cb2039d0065bb2b0083762df92d7b1
--- /dev/null
+++ b/src/components/__tests__/QuestionBox.spec.ts
@@ -0,0 +1,42 @@
+import { describe, it, expect } from 'vitest'
+
+import { mount } from '@vue/test-utils';
+import QuestionBox from '@/components/QuestionBox.vue';
+
+describe('QuestionBox', () => {
+  it('renders props correctly', () => {
+    // Define props
+    const props = {
+      image: '/path/to/image.jpg',
+      questionNumber: 1,
+      tags: ['tag1', 'tag2'],
+      question: ['Sample question line 1', 'Sample question line 2'],
+    };
+
+    // Mount the component with props
+    const wrapper = mount(QuestionBox, {
+      props,
+    });
+
+    // Assert that props are rendered correctly
+    expect(wrapper.find('img').attributes('src')).toBe(props.image);
+    expect(wrapper.find('label[for="number"]').text()).toBe(props.questionNumber.toString());
+    
+    // Construct the expected question string
+    const expectedQuestion = JSON.stringify(props.question, null, 2); // Use JSON.stringify
+    const receivedQuestion = wrapper.find('label[for="question"]').text();
+    expect(receivedQuestion).toBe(expectedQuestion);
+  });
+
+  it('renders default image if image prop is not provided', () => {
+    const wrapper = mount(QuestionBox, {
+      props: {
+        questionNumber: 1,
+        tags: ['tag1', 'tag2'],
+        question: ['Sample question line 1', 'Sample question line 2'],
+      },
+    });
+
+    expect(wrapper.find('img').attributes('src')).toBe('/src/assets/trivio.svg');
+  });
+});
diff --git a/src/components/__tests__/TrivioCard.spec.ts b/src/components/__tests__/TrivioCard.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b53907d668652a3675e6b0e9e13533dc13d68e5c
--- /dev/null
+++ b/src/components/__tests__/TrivioCard.spec.ts
@@ -0,0 +1,48 @@
+import { describe, it, expect } from 'vitest'
+
+import { mount } from '@vue/test-utils';
+import TrivioCard from '@/components/TrivioCard.vue';
+
+describe('TrivioCard', () => {
+  it('renders props correctly', () => {
+    // Define props
+    const props = {
+      title: 'Sample Quiz',
+      image: '/path/to/image.jpg',
+      category: 'Sample Category',
+      numberOfQuestion: 10,
+      username: 'sampleUser',
+      difficulty: 'Easy',
+      media: '/path/to/media.jpg',
+    };
+
+    // Mount the component with props
+    const wrapper = mount(TrivioCard, {
+      props,
+    });
+
+    // Assert that props are rendered correctly
+    expect(wrapper.find('.title').text()).toBe(props.title);
+    expect(wrapper.find('.category').text()).toContain(props.category);
+    expect(wrapper.find('.question').text()).toContain(`${props.numberOfQuestion} Questions`);
+    expect(wrapper.find('.user').text()).toBe(props.username);
+    expect(wrapper.find('.difficulty').text()).toBe(props.difficulty);
+    expect(wrapper.find('img').attributes('src')).toBe(props.media);
+  });
+
+  it('renders default image if image prop is not provided', () => {
+    // Mount the component without image prop
+    const wrapper = mount(TrivioCard, {
+      props: {
+        title: 'Sample Quiz',
+        category: 'Sample Category',
+        numberOfQuestion: 10,
+        username: 'sampleUser',
+        difficulty: 'Easy',
+      },
+    });
+
+    // Assert that default image is rendered
+    expect(wrapper.find('img').attributes('src')).toBe('/src/assets/trivio.svg');
+  });
+});
diff --git a/src/components/__tests__/UserSchema.spec.ts b/src/components/__tests__/UserSchema.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8d9d14990020891add86545f773db8bc3785a0da
--- /dev/null
+++ b/src/components/__tests__/UserSchema.spec.ts
@@ -0,0 +1,40 @@
+import { describe, it, expect } from 'vitest'
+
+import { mount } from '@vue/test-utils';
+import UserSchema from '@/components/UserSchema.vue';
+
+describe('UserSchema Component', () => {
+  it('renders correctly with default props', async () => {
+    // Mount the component
+    const wrapper = mount(UserSchema);
+
+    // Assert that the component renders correctly
+    expect(wrapper.exists()).toBe(true);
+    expect(wrapper.find('h1').text()).toBe('Login');
+    expect(wrapper.find('#username').exists()).toBe(true);
+    expect(wrapper.find('#password').exists()).toBe(true);
+    expect(wrapper.find('#email').exists()).toBe(false); // Email input should not be rendered by default
+    expect(wrapper.find('button').text()).toBe('Login');
+    expect(wrapper.find('#loginStatus').text()).toBe('');
+  });
+
+  it('renders correctly with custom props', async () => {
+    // Mount the component with custom props
+    const wrapper = mount(UserSchema, {
+      props: {
+        buttonText: 'Sign Up',
+        headerText: 'Create Account',
+        status: 'Invalid username or password',
+      },
+    });
+
+    // Assert that the component renders correctly with custom props
+    expect(wrapper.exists()).toBe(true);
+    expect(wrapper.find('h1').text()).toBe('Create Account');
+    expect(wrapper.find('#username').exists()).toBe(true);
+    expect(wrapper.find('#password').exists()).toBe(true);
+    expect(wrapper.find('#email').exists()).toBe(true); // Email input should be rendered with custom props
+    expect(wrapper.find('button').text()).toBe('Sign Up');
+    expect(wrapper.find('#loginStatus').text()).toBe('Invalid username or password');
+  });
+});