From 98b43385b692975c6d6105a4e3bb7e9b762066ab Mon Sep 17 00:00:00 2001
From: Gia Hy Nguyen <giahy03@outlook.com>
Date: Sun, 7 Apr 2024 20:20:01 +0200
Subject: [PATCH 1/4] Added vitest unit tests

---
 src/components/__tests__/HelloWorld.spec.ts  | 11 -----
 src/components/__tests__/HistoryBox.spec.ts  | 39 ++++++++++++++++
 src/components/__tests__/QuestionBox.spec.ts | 42 +++++++++++++++++
 src/components/__tests__/TrivioCard.spec.ts  | 48 ++++++++++++++++++++
 src/components/__tests__/UserSchema.spec.ts  | 40 ++++++++++++++++
 5 files changed, 169 insertions(+), 11 deletions(-)
 delete mode 100644 src/components/__tests__/HelloWorld.spec.ts
 create mode 100644 src/components/__tests__/HistoryBox.spec.ts
 create mode 100644 src/components/__tests__/QuestionBox.spec.ts
 create mode 100644 src/components/__tests__/TrivioCard.spec.ts
 create mode 100644 src/components/__tests__/UserSchema.spec.ts

diff --git a/src/components/__tests__/HelloWorld.spec.ts b/src/components/__tests__/HelloWorld.spec.ts
deleted file mode 100644
index 2533202..0000000
--- 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 0000000..cf9a540
--- /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 0000000..ff17e65
--- /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 0000000..b53907d
--- /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 0000000..8d9d149
--- /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');
+  });
+});
-- 
GitLab


From a36c5cdc171c97d88ec90be0b31edd6a80d76798 Mon Sep 17 00:00:00 2001
From: Gia Hy Nguyen <giahy03@outlook.com>
Date: Sun, 7 Apr 2024 20:21:25 +0200
Subject: [PATCH 2/4] Added cypress integration tests

---
 cypress.config.ts                      |  2 +-
 cypress/e2e/example.cy.ts              |  8 ---
 cypress/e2e/frontpage/login.cy.ts      | 29 +++++++++++
 cypress/e2e/frontpage/signup.cy.ts     | 56 ++++++++++++++++++++
 cypress/e2e/mainpage/contact.cy.ts     | 39 ++++++++++++++
 cypress/e2e/mainpage/discovery.cy.ts   | 72 ++++++++++++++++++++++++++
 cypress/e2e/mainpage/editTrivios.cy.ts | 38 ++++++++++++++
 cypress/e2e/mainpage/history.cy.ts     | 18 +++++++
 cypress/e2e/mainpage/makeTrivio.cy.ts  | 42 +++++++++++++++
 cypress/e2e/mainpage/myTrivios.cy.ts   | 27 ++++++++++
 cypress/e2e/mainpage/profile.cy.ts     | 25 +++++++++
 cypress/support/commands.ts            | 58 ++++++++-------------
 package.json                           |  4 +-
 13 files changed, 370 insertions(+), 48 deletions(-)
 delete mode 100644 cypress/e2e/example.cy.ts
 create mode 100644 cypress/e2e/frontpage/login.cy.ts
 create mode 100644 cypress/e2e/frontpage/signup.cy.ts
 create mode 100644 cypress/e2e/mainpage/contact.cy.ts
 create mode 100644 cypress/e2e/mainpage/discovery.cy.ts
 create mode 100644 cypress/e2e/mainpage/editTrivios.cy.ts
 create mode 100644 cypress/e2e/mainpage/history.cy.ts
 create mode 100644 cypress/e2e/mainpage/makeTrivio.cy.ts
 create mode 100644 cypress/e2e/mainpage/myTrivios.cy.ts
 create mode 100644 cypress/e2e/mainpage/profile.cy.ts

diff --git a/cypress.config.ts b/cypress.config.ts
index 0f66080..f80530a 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 7554c35..0000000
--- 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 0000000..754f077
--- /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 0000000..806dc78
--- /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 0000000..3e6960c
--- /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 0000000..7e9a351
--- /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 0000000..0a8c0fc
--- /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 0000000..08cec4c
--- /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 0000000..0fc76e0
--- /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 0000000..bd3363f
--- /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 0000000..2cf0410
--- /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 9b7bb8e..843daae 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 d8f9c1c..7726d73 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",
-- 
GitLab


From da2476b3c0160c2adb3aa28dd30357b70b2f8e62 Mon Sep 17 00:00:00 2001
From: Gia Hy Nguyen <giahy03@outlook.com>
Date: Sun, 7 Apr 2024 20:32:47 +0200
Subject: [PATCH 3/4] Added future work and test section

---
 README.md | 159 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 83 insertions(+), 76 deletions(-)

diff --git a/README.md b/README.md
index 53ff42d..2856ba8 100644
--- a/README.md
+++ b/README.md
@@ -1,93 +1,100 @@
-# frontend_fullstack
+# 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")
+- [Installation](#installation)
+- [Usage](#usage)
+- [Tests](#tests)
+- [Dependencies](#dependencies)
+- [Future work](#future-work)
+- [Authors](#authors)
+
+## 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
 
-
-## Getting started
-
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
-
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
-
-## Add your files
-
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
-
-```
-cd existing_repo
-git remote add origin https://gitlab.stud.idi.ntnu.no/team_fullastack/frontend_fullstack.git
-git branch -M main
-git push -uf origin main
+2. Clone the repository 
+```bash 
+git clone https://gitlab.stud.idi.ntnu.no/team_fullastack/frontend_fullstack.git
 ```
 
-## Integrate with your tools
-
-- [ ] [Set up project integrations](https://gitlab.stud.idi.ntnu.no/team_fullastack/frontend_fullstack/-/settings/integrations)
-
-## Collaborate with your team
-
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
-
-***
-
-# Editing this README
-
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
-
-## Suggestions for a good README
-
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
-
-## Name
-Choose a self-explaining name for your project.
+3. Navigate to frontend_fullstack:
+```bash
+cd frontend_fullstack
+```
 
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
+4. Install dependencies:
+```bash
+npm install
+```
 
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
+## Usage 
+1. Run the frontend application.
+```bash
+npm run dev
+```
+This will start the application locally and display the URL where it can be accessed in your shell. 
 
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
+2. Navigate to this URL in your web browser to view the application
 
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
+## Tests
 
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
+### Cypress
+1. Ensure that both the backend and frontend applications are running.
 
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
+2. Run Cypress interaction tests:
+'''bash
+npm run test:e2e
+'''
 
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
+### Vitest 
+1. Run Vitest unit tests:
+'''bash
+npm run test:unit
+'''
 
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
+## Dependencies
+- Vue.js
+- Vite
+- Axios
+- Vue Router
+- Pinia
+- Cypress
+- Vitest
 
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
+## Future work
 
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
+### 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.
 
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
+### Additional Admin Functionalities
+Expand the capabilities of the admin dashboard to provide more control and management options.
 
-## License
-For open source projects, say how it is licensed.
+### 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.
 
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
+## Authors
+Gia Hy Nguyen  
+Tini Tran  
+Vilde Min Vikan  
-- 
GitLab


From 6609ddddffb5f56a24146f71cc6defd0c3d4968d Mon Sep 17 00:00:00 2001
From: Gia Hy Nguyen <giahy03@outlook.com>
Date: Sun, 7 Apr 2024 20:38:34 +0200
Subject: [PATCH 4/4] fix bash commands

---
 README.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 646a7dc..e8951d8 100644
--- a/README.md
+++ b/README.md
@@ -113,15 +113,15 @@ This will start the application locally and display the URL where it can be acce
 1. Ensure that both the backend and frontend applications are running.
 
 2. Run Cypress interaction tests:
-'''bash
+```bash
 npm run test:e2e
-'''
+```
 
 ### Vitest 
 1. Run Vitest unit tests:
-'''bash
+```bash
 npm run test:unit
-'''
+```
 
 ## Dependencies
 - Vue.js
-- 
GitLab