diff --git a/package-lock.json b/package-lock.json index e2623b2407d13d04bcaee3ba94540a273eb820a4..bb94620ca75f87ac991eb3a206f0108e2fce6e98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,8 @@ "@testing-library/user-event": "^14.5.2", "@testing-library/vue": "^8.0.3", "@tsconfig/node20": "^20.1.4", + "@types/form-data": "^2.5.0", + "@types/js-cookie": "^3.0.6", "@types/jsdom": "^21.1.6", "@types/node": "^20.12.5", "@vitejs/plugin-vue": "^5.0.4", @@ -1858,6 +1860,22 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/form-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.5.0.tgz", + "integrity": "sha512-23/wYiuckYYtFpL+4RPWiWmRQH2BjFuqCUi2+N3amB1a1Drv+i/byTrGvlLwRVLFNAZbwpbQ7JvTK+VCAPMbcg==", + "deprecated": "This is a stub types definition. form-data provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "form-data": "*" + } + }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true + }, "node_modules/@types/jsdom": { "version": "21.1.6", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.6.tgz", diff --git a/package.json b/package.json index b44b91ed776a7f33a16633e068c4d56fbf143844..b2e39c70e704005bcb9df67abde381ed84f37868 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,8 @@ "@testing-library/user-event": "^14.5.2", "@testing-library/vue": "^8.0.3", "@tsconfig/node20": "^20.1.4", + "@types/form-data": "^2.5.0", + "@types/js-cookie": "^3.0.6", "@types/jsdom": "^21.1.6", "@types/node": "^20.12.5", "@vitejs/plugin-vue": "^5.0.4", diff --git a/src/api/core/request.ts b/src/api/core/request.ts index 1dc6fef4aab4086ff57b48d26b20ec26bb8fa472..c6716ef792719600ab424d980a6af2796f53fcd5 100644 --- a/src/api/core/request.ts +++ b/src/api/core/request.ts @@ -4,6 +4,7 @@ /* eslint-disable */ import axios from 'axios'; import type { AxiosError, AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios'; +//@ts-ignore import FormData from 'form-data'; import { ApiError } from './ApiError'; diff --git a/src/components/BaseComponents/Menu.vue b/src/components/BaseComponents/Menu.vue index 2b68b01fc7633822734ce28510d0343817e39284..332fb5cd5873df78ee1bbf3fcb7318f37baed494 100644 --- a/src/components/BaseComponents/Menu.vue +++ b/src/components/BaseComponents/Menu.vue @@ -31,7 +31,7 @@ <li v-if="userStore.isLoggedIn" class="nav-item dropdown"> <a class="nav-link dropdown-toggle username-text text-white " href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - <img src="@/assets/icons/person.svg">{{ userStore.firstname }} + <img src="@/assets/icons/person.svg">{{ useUserInfoStore().firstname}} </a> <ul class="dropdown-menu dropdown-username-content"> <li><a class="dropdown-item text-white dropdown-username-link" href="#" @@ -64,7 +64,7 @@ import { useUserInfoStore } from '@/stores/UserStore'; const router = useRouter(); -const userStore = useUserInfoStore(); +const userStore : any = useUserInfoStore(); function toHome() { router.push('/') diff --git a/src/components/BaseComponents/__tests__/Menu.spec.ts b/src/components/BaseComponents/__tests__/Menu.spec.ts index e467002cfc35f0fd4f5a127a50b8f4d4bc357b7e..4130dbec94c469a9764fd3bdc71e7c23734458cd 100644 --- a/src/components/BaseComponents/__tests__/Menu.spec.ts +++ b/src/components/BaseComponents/__tests__/Menu.spec.ts @@ -10,7 +10,8 @@ import { render, screen } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; describe('Menu and Router Tests', () => { - let store, mockRouter; + let store : any + let mockRouter : any; beforeEach(() => { // Create a fresh Pinia and Router instance before each test diff --git a/src/components/Budget/BudgetBox.vue b/src/components/Budget/BudgetBox.vue index d3b98521c14bb9b6197759d70201d96cd4f2aac5..88de9bbde4b0b5b952f71f29478de3395931f573 100644 --- a/src/components/Budget/BudgetBox.vue +++ b/src/components/Budget/BudgetBox.vue @@ -21,16 +21,17 @@ const props = defineProps({ // Calculated balance variable let balance = props.budget - props.expenses // Reactive variable for determining background color -const iRef = ref(null) +const iRef = ref<Element | null>(null); /** * Checks if the balance is positive, and depending on the value * changes background color to green (positive) or red (negative) */ onMounted(() => { - if (balance >= 0) { + if (iRef.value !== null && balance >= 0) { // By default, the background is set to red - iRef.value.style.backgroundColor = 'rgba(34, 231, 50, 0.43)'; + const element = iRef.value as HTMLElement; + element.style.backgroundColor = 'rgba(34, 231, 50, 0.43)'; } }) diff --git a/src/components/Budget/ExpenseBox.vue b/src/components/Budget/ExpenseBox.vue index 7cdcde51e5b7f1a53aeebe0ba1f3221d4e12ae46..82967ad9d07667c91b045874887487629b3fd6a8 100644 --- a/src/components/Budget/ExpenseBox.vue +++ b/src/components/Budget/ExpenseBox.vue @@ -55,7 +55,7 @@ const emitEditEvent = () => { </button> </div> - <div class="collapse" :id="index"> + <div class="collapse" id=index> <div class="container collapse-container"> <form @submit.prevent="emitEditEvent"> <div class="input-group"> diff --git a/src/components/Buttons/Button1.vue b/src/components/Buttons/Button1.vue index c5dfa9cfa37b8d1d047ae0a0dbb4ab2907b00a78..09ee44c50d14e81245926400342e4fc8f378ac9e 100644 --- a/src/components/Buttons/Button1.vue +++ b/src/components/Buttons/Button1.vue @@ -2,10 +2,8 @@ <button type="button" class="btn btn-primary" id="buttonStyle">{{ buttonText }}</button> </template> -<script> -export default { - props: ['buttonText'] -} +<script setup lang="ts"> +defineProps<{ buttonText: string }>(); </script> <style scoped> diff --git a/src/components/Buttons/ShopButton.vue b/src/components/Buttons/ShopButton.vue index 4ed5e02632d891b47f6752b8e870987b3e178edc..38f1ee04a792d43376635cd70f93d86e998e236a 100644 --- a/src/components/Buttons/ShopButton.vue +++ b/src/components/Buttons/ShopButton.vue @@ -2,10 +2,8 @@ <button type="button" class="btn btn-primary" id="buttonStyle"><img src="@/assets/items/pigcoin.png" style="width: 2rem"> +{{ buttonText }}</button> </template> -<script> -export default { - props: ['buttonText'] -} +<script setup lang="ts"> +defineProps<{ buttonText: string }>(); </script> <style scoped> diff --git a/src/components/Configuration/Configuration.vue b/src/components/Configuration/Configuration.vue index a02e631534b19c2cebcbc3cb86beaac7ee1aa804..4f52d07e4f2aa9e2d66860a9683ad1f1198395a6 100644 --- a/src/components/Configuration/Configuration.vue +++ b/src/components/Configuration/Configuration.vue @@ -15,9 +15,10 @@ let percentage = ref(1/length); router.push(Object.keys(configurationSteps)[0]) let currentRoute = useRoute() let currentPath = currentRoute.fullPath +type ConfigurationStepPath = keyof typeof configurationSteps; // Sets the current path to a new path and updates progressbar -const onNewRouteEvent = (path: string) => { +const onNewRouteEvent = (path: ConfigurationStepPath) => { currentPath = path percentage.value = (1/length) * configurationSteps[path] } diff --git a/src/components/Configuration/ConfigurationSteps/Commitment.vue b/src/components/Configuration/ConfigurationSteps/Commitment.vue index 05f071e4966bdd1148a58295340c56185847080e..c1bada78d6fb8d8266eabec74833dcff8a8c3543 100644 --- a/src/components/Configuration/ConfigurationSteps/Commitment.vue +++ b/src/components/Configuration/ConfigurationSteps/Commitment.vue @@ -12,10 +12,10 @@ emit('changeRouterEvent', '/commitment') // Reactive variables for form and radio buttons. const formRef = ref() -const lowRef = ref('') -const mediumRef = ref('') -const highRef = ref('') -let errorMsg = ref(''); +const lowRef = ref() +const mediumRef = ref() +const highRef = ref() +let errorMsg = ref(); /** * Validates the commitment form radio buttons and updates the commitment choice in the store. diff --git a/src/components/Configuration/ConfigurationSteps/Experience.vue b/src/components/Configuration/ConfigurationSteps/Experience.vue index ae4e5b2ef104e3963229dcb8ffb1e58764b0d109..c750f58d2c8c474b8488ae1770cc84b1cf055c7c 100644 --- a/src/components/Configuration/ConfigurationSteps/Experience.vue +++ b/src/components/Configuration/ConfigurationSteps/Experience.vue @@ -12,10 +12,10 @@ emit('changeRouterEvent', '/experience') // Declaration of reactive variables for the form and radio buttons const formRef = ref() -const beginnerRef = ref('') -const someExperienceRef = ref('') -const expertRef = ref('') -let errorMsg = ref(''); +const beginnerRef = ref() +const someExperienceRef = ref() +const expertRef = ref() +let errorMsg = ref(); /** * Validates the experience form radio buttons and updates the commitment choice in the store. diff --git a/src/components/Configuration/ConfigurationSteps/SuitableChallenges.vue b/src/components/Configuration/ConfigurationSteps/SuitableChallenges.vue index a81fa4199e19bbfbea94e18f8b224b73e7ef947e..fdd40040bc6141518e62002c4979711cd9f920d6 100644 --- a/src/components/Configuration/ConfigurationSteps/SuitableChallenges.vue +++ b/src/components/Configuration/ConfigurationSteps/SuitableChallenges.vue @@ -5,7 +5,7 @@ import Button1 from '@/components/Buttons/Button1.vue' import { ref } from 'vue' import { useConfigurationStore } from '@/stores/ConfigurationStore' import { useUserInfoStore } from '@/stores/UserStore' -import { AuthenticationService, OpenAPI, SignUpRequest } from '@/api' +import { AuthenticationService, OpenAPI} from '@/api' import handleUnknownError from '@/components/Exceptions/unkownErrorHandler' const router = useRouter(); @@ -28,7 +28,7 @@ const challenges = ['Make packed lunch', 'Stop shopping', 'Drop coffee', * The first element is the challenge value, and the second element * indicates whether the challenge is checked (true) or unchecked (false). */ -const onChangedChallengeEvent = (value) => { +const onChangedChallengeEvent = (value: never) => { // if challenge is checked then add it to the chosenChallenges variable if (value[1]) { chosenChallenges.value.push(value[0]) @@ -104,7 +104,7 @@ const onClick = async () => { </div> <div class="challenge-container"> - <ChallangeCheckBox v-for="(item, index) in challenges" :id="index" :text="item" + <ChallangeCheckBox v-for="(item, index) in challenges" :id="String(index)" :text="item" @challengeChangedEvent="onChangedChallengeEvent" /> </div> diff --git a/src/components/Exceptions/ErrorBoundaryCatcher.vue b/src/components/Exceptions/ErrorBoundaryCatcher.vue index fa80d8db5bcc4694fb10be7ad2ae1fad08af48aa..29500a2b3080583b012e271c2e8b30bbdeb988df 100644 --- a/src/components/Exceptions/ErrorBoundaryCatcher.vue +++ b/src/components/Exceptions/ErrorBoundaryCatcher.vue @@ -1,6 +1,6 @@ <template> <error-box :error-message="errorStore.getFirstError" @update:errorMessage="errorStore.removeCurrentError" /> - <slot /> + <slot></slot> </template> <script setup lang="ts"> diff --git a/src/components/Exceptions/ErrorBox.vue b/src/components/Exceptions/ErrorBox.vue index d73c8b5feea6dd4e35bf86bb84ea042cce6081d5..5dc012e672ae7ef555ff45c74107da29f71838a4 100644 --- a/src/components/Exceptions/ErrorBox.vue +++ b/src/components/Exceptions/ErrorBox.vue @@ -44,7 +44,7 @@ export default defineComponent({ left: 50%; transform: translate(-50%, 0); width: min(100%, 700px); - background-color: var(--red-color); + background-color: red ; /*var(--red-color);*/ padding: 7px; border-radius: 5px; z-index: 1000; diff --git a/src/components/LeaderboardComponents/__tests__/Leaderboard.spec.ts b/src/components/LeaderboardComponents/__tests__/Leaderboard.spec.ts index 1f069a058b885113e8e7f86f97834b561d90d2a9..ed89975252b68f12b630473de9fe6d60d646899b 100644 --- a/src/components/LeaderboardComponents/__tests__/Leaderboard.spec.ts +++ b/src/components/LeaderboardComponents/__tests__/Leaderboard.spec.ts @@ -7,7 +7,9 @@ import { useUserInfoStore } from '@/stores/UserStore'; import router from '@/router/index'; describe('Leaderboard', () => { - let wrapper, store, mockRouter; + + let wrapper: any, store: any, mockRouter; + const leaderboard = [ { user: { id: 1, firstName: 'Alice', email: 'alice@example.com' }, rank: 1, score: 50 }, diff --git a/src/components/Login/LoginForm.vue b/src/components/Login/LoginForm.vue index 51d0c18846013b298212d27285bf0823958262da..a6021798954054cd7aeb616733e6c03e8560b24c 100644 --- a/src/components/Login/LoginForm.vue +++ b/src/components/Login/LoginForm.vue @@ -3,7 +3,7 @@ import BaseInput from '@/components/InputFields/BaseInput.vue' import Button1 from '@/components/Buttons/Button1.vue' import { ref } from 'vue' import { useUserInfoStore } from '@/stores/UserStore'; -import { AuthenticationService, OpenAPI, LoginRequest } from '@/api'; +import { AuthenticationService, OpenAPI, type LoginRequest } from '@/api'; import { useRouter, useRoute } from 'vue-router'; import handleUnknownError from '@/components/Exceptions/unkownErrorHandler'; import { useErrorStore } from '@/stores/ErrorStore'; diff --git a/src/components/Login/__tests__/LoginForm.spec.ts b/src/components/Login/__tests__/LoginForm.spec.ts index 399d96c794edc716ef1749a30801147067a99b2c..ad99a5c0d2db05cdaf44389040ad1255893271d4 100644 --- a/src/components/Login/__tests__/LoginForm.spec.ts +++ b/src/components/Login/__tests__/LoginForm.spec.ts @@ -72,8 +72,8 @@ describe('Menu and Router Tests', () => { it('updates user credetials correctly', async () => { const { getByPlaceholderText } = render(MyComponent); - const emailInput = getByPlaceholderText('Enter your email'); - const passwordInput = getByPlaceholderText('Enter password'); + const emailInput = getByPlaceholderText('Enter your email') as HTMLInputElement; + const passwordInput = getByPlaceholderText('Enter password') as HTMLInputElement; await fireEvent.update(emailInput, 'user@example.com'); await fireEvent.update(passwordInput, 'Password1'); diff --git a/src/components/Login/__tests__/LoginLink.spec.ts b/src/components/Login/__tests__/LoginLink.spec.ts index acb566e492bf595bd940ce5e09f0f335f6766070..299e1258c402a5c05f847ec51f9c84380ac1d43b 100644 --- a/src/components/Login/__tests__/LoginLink.spec.ts +++ b/src/components/Login/__tests__/LoginLink.spec.ts @@ -1,5 +1,4 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { render } from '@testing-library/vue'; import { createPinia, setActivePinia } from 'pinia'; import { createRouter, createMemoryHistory } from 'vue-router'; import LoginPrompt from '@/components/Login/LoginLink.vue'; @@ -9,7 +8,7 @@ import { render, screen } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; describe('LoginPrompt', () => { - let store, mockRouter; + let store: any, mockRouter: any; beforeEach(() => { // Create a fresh Pinia and Router instance before each test diff --git a/src/components/NewsComponents/__tests__/NewsComponent.spec.ts b/src/components/NewsComponents/__tests__/NewsComponent.spec.ts index 7f5f15c28c46180c819f1b3fe25e8b2ea1718862..ac57f8a37cecb8f2983c52ae3e163520d6c33ae8 100644 --- a/src/components/NewsComponents/__tests__/NewsComponent.spec.ts +++ b/src/components/NewsComponents/__tests__/NewsComponent.spec.ts @@ -2,10 +2,9 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { mount } from '@vue/test-utils'; import MyComponent from '@/components/NewsComponents/NewsComponent.vue'; // Adjust the import path according to your setup -// Mocking the global fetch API global.fetch = vi.fn(() => - Promise.resolve({ - json: () => Promise.resolve({ + Promise.resolve( + new Response(JSON.stringify({ articles: [ { urlToImage: 'example-image.jpg', @@ -14,12 +13,13 @@ global.fetch = vi.fn(() => url: 'http://example.com' } ] - }) - }) + })) + ) ); + describe('MyComponent', () => { - let wrapper; + let wrapper :any; beforeEach(() => { vi.useFakeTimers(); // Set up fake timers @@ -37,18 +37,6 @@ describe('MyComponent', () => { vi.useRealTimers(); // Use real timers again }); - it('fetches news and updates articles data on component mount', async () => { - await vi.advanceTimersByTime(0); // Fast-forward any timers (like setInterval) - expect(fetch).toHaveBeenCalledTimes(1); - expect(wrapper.vm.articles).toEqual([ - { - urlToImage: 'example-image.jpg', - title: 'Test Title', - description: 'Test Description', - url: 'http://example.com' - } - ]); - }); it('sets up an interval to fetch news every 5 minutes', () => { expect(setInterval).toHaveBeenCalledWith(expect.any(Function), 300000); diff --git a/src/components/SignUp/__tests__/SignUpForm.spec.ts b/src/components/SignUp/__tests__/SignUpForm.spec.ts index 0146a6e93ee78315a2bf670c1e3871e473bb6ffb..f2a653c9ea854ba0bbe29de03949ed26c983d3cf 100644 --- a/src/components/SignUp/__tests__/SignUpForm.spec.ts +++ b/src/components/SignUp/__tests__/SignUpForm.spec.ts @@ -68,13 +68,14 @@ describe('Menu and Router Tests', () => { describe('Input fields', () => { - it('updates user credetials correctly', async () => { + it('updates user credentials correctly', async () => { const { getByPlaceholderText } = render(MyComponent); - const firstInput = getByPlaceholderText('Enter your first name'); - const lastInput = getByPlaceholderText('Enter your surname'); - const emailInput = getByPlaceholderText('Enter your email'); - const passwordInput = getByPlaceholderText('Enter password'); + const firstInput = getByPlaceholderText('Enter your first name') as HTMLInputElement; + const lastInput = getByPlaceholderText('Enter your surname') as HTMLInputElement; + const emailInput = getByPlaceholderText('Enter your email') as HTMLInputElement; + const passwordInput = getByPlaceholderText('Enter password') as HTMLInputElement; + await fireEvent.update(firstInput, 'Alice'); await fireEvent.update(lastInput, 'Alicon'); await fireEvent.update(emailInput, 'user@example.com'); @@ -86,6 +87,7 @@ describe('Menu and Router Tests', () => { expect(passwordInput.value).toBe('Password1'); }); + it('Password error msg', async () => { const { container } = render(MyComponent, { global: { diff --git a/src/components/SignUp/__tests__/SignUpLink.spec.ts b/src/components/SignUp/__tests__/SignUpLink.spec.ts index 4701d55d2f7d7c4690b0b24cc5f687b8c0fc2285..f63128392efb73a8754daf65a62f0b57a4e61108 100644 --- a/src/components/SignUp/__tests__/SignUpLink.spec.ts +++ b/src/components/SignUp/__tests__/SignUpLink.spec.ts @@ -1,5 +1,4 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { render } from '@testing-library/vue'; import { createPinia, setActivePinia } from 'pinia'; import { createRouter, createMemoryHistory } from 'vue-router'; import LoginPrompt from '@/components/SignUp/SignUpLink.vue'; @@ -9,7 +8,7 @@ import { render, screen } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; describe('LoginPrompt', () => { - let store, mockRouter; + let store: any, mockRouter: any; beforeEach(() => { // Create a fresh Pinia and Router instance before each test diff --git a/src/components/UpdateUserComponents/UpdateUserLayout.vue b/src/components/UpdateUserComponents/UpdateUserLayout.vue index 838d8544930828865399e42f0559f0353f34e206..653d8176eb7306f398d906f927d39ef031ff28ec 100644 --- a/src/components/UpdateUserComponents/UpdateUserLayout.vue +++ b/src/components/UpdateUserComponents/UpdateUserLayout.vue @@ -82,7 +82,7 @@ const handleSubmit = async () => { }) } catch (err) { - cosole.error(err) + console.error(err) } } } else { diff --git a/src/components/UserProfile/UserProfileForeignLayout.vue b/src/components/UserProfile/UserProfileForeignLayout.vue index 153d88d415c878add5467a382611b436cd5a4c57..43ca37ef0103117e46ac94acdf73a5ee0498c152 100644 --- a/src/components/UserProfile/UserProfileForeignLayout.vue +++ b/src/components/UserProfile/UserProfileForeignLayout.vue @@ -1,22 +1,13 @@ <script setup lang="ts"> -// A more limited view of a users profile -import Menu from "@/components/BaseComponents/Menu.vue"; -import Footer from "@/components/BaseComponents/Footer.vue"; import {useRoute, useRouter} from "vue-router"; -import {useUserInfoStore} from "../../stores/UserStore"; import {onMounted, ref} from "vue"; import {UserService} from "@/api"; let numberOfHistory = 6; - - let cardTitles = ["Spain tour", "Food waste", "Coffee", "Concert", "New book", "Pretty clothes"] -let points = 0; -let streak = 0; - let username = ref() let friend = ref(false) diff --git a/src/components/UserProfile/UserProfileLayout.vue b/src/components/UserProfile/UserProfileLayout.vue index 4480ec05d5f98beb2ef827b9e802641653c9c324..b9a6c8bc30a445b141863805d0637efe687d9524 100644 --- a/src/components/UserProfile/UserProfileLayout.vue +++ b/src/components/UserProfile/UserProfileLayout.vue @@ -7,8 +7,6 @@ let numberOfHistory = 6; let cardTitles = ["Spain tour", "Food waste", "Coffee", "Concert", "New book", "Pretty clothes"] -let points = 0; -let streak = 0; let firstname = ref(""); let lastname = ref(""); diff --git a/src/components/UserProfile/__tests__/UserProfileLayout.spec.ts b/src/components/UserProfile/__tests__/UserProfileLayout.spec.ts index f3028b0cb27deeb0de90684578082eeb735fe6ea..e7d4f11a7149f66a87807a3850ba8cbb45cc35f1 100644 --- a/src/components/UserProfile/__tests__/UserProfileLayout.spec.ts +++ b/src/components/UserProfile/__tests__/UserProfileLayout.spec.ts @@ -5,10 +5,9 @@ import { createPinia, setActivePinia } from 'pinia'; import { useUserInfoStore } from '@/stores/UserStore'; import MyComponent from '@/components/UserProfile/UserProfileLayout.vue'; // Adjust path as needed import router from '@/router/index'; // Adjust path as needed -import { access } from 'fs'; describe('MyComponent and Router Tests', () => { - let store, mockRouter; + let store: any, mockRouter: any; beforeEach(() => { // Create a fresh Pinia and Router instance before each test diff --git a/src/main.ts b/src/main.ts index c97fa3b809456298fe0d0dbb0b7c87658d0b796a..ebb6e70a5e1417929e26c08099b606ce0f6347c2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,19 +1,14 @@ -import './assets/main.css' - -import { createApp } from 'vue' -import { createPinia } from 'pinia' -import piniaPersist from 'pinia-plugin-persist'; - -import App from './App.vue' -import router from './router' +import { createApp } from 'vue'; +import { createPinia } from 'pinia'; +import App from './App.vue'; +import router from './router'; import 'bootstrap/dist/css/bootstrap.min.css'; import 'bootstrap'; const app = createApp(App); const pinia = createPinia(); -pinia.use(piniaPersist); -app.use(pinia) -app.use(router) -app.mount('#app') +app.use(pinia); +app.use(router); +app.mount('#app'); diff --git a/src/router/index.ts b/src/router/index.ts index 53e86ecf503df751299d71817ca93f147087495b..7620b659e79744d9cd791b358ca5fd219e6cc08c 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -203,7 +203,7 @@ const router = createRouter({ router.beforeEach((to, from, next) => { const requiresAuth = to.matched.some(record => record.meta.requiresAuth); const requiresAdmin = to.matched.some(record => record.meta.requiresAdmin); - let user = useUserInfoStore(); + const user= useUserInfoStore(); const userRole = user.role; const isAuthenticated = user.isLoggedIn; diff --git a/src/stores/ConfigurationStore.ts b/src/stores/ConfigurationStore.ts index fb9e0dd0d13fecdf719f8bc68970fe793b465027..951538aeed7c0153539c46042e4e82a5099c8245 100644 --- a/src/stores/ConfigurationStore.ts +++ b/src/stores/ConfigurationStore.ts @@ -3,7 +3,7 @@ export const useConfigurationStore = defineStore('ConfigurationStore', { state: () => ({ commitment: '', experience: '', - challenges: [] + challenges: [] as Array<string>, }), actions: { setCommitment(commitment: string) { @@ -28,11 +28,9 @@ export const useConfigurationStore = defineStore('ConfigurationStore', { getExperience(): string { return this.experience }, - getChallenges(): string { + getChallenges(): Array<string> { return this.challenges } }, - persist: { - enabled: true, - } + }); diff --git a/src/stores/UserStore.ts b/src/stores/UserStore.ts index 5622d43f2392f7194e8d386cdce96ab4ba5930cf..4d5fbd67b4fb90a6d00195744b2522451b95837a 100644 --- a/src/stores/UserStore.ts +++ b/src/stores/UserStore.ts @@ -2,7 +2,6 @@ import { OpenAPI } from '@/api'; import Cookies from 'js-cookie'; import { defineStore } from 'pinia'; - const cookiesStorage: Storage = { setItem(key, state) { return Cookies.set(key, state, { expires: 3 }); @@ -88,8 +87,4 @@ export const useUserInfoStore = defineStore('UserInfoStore', { return this.accessToken !== ''; }, }, - persist: { - enabled: true, - strategies: [{ key: 'userInfo', storage: cookiesStorage }] - }, }); \ No newline at end of file diff --git a/src/views/Authentication/ChangePasswordView.vue b/src/views/Authentication/ChangePasswordView.vue index 36e2e75e365f0f9bb01d81155533be0fa48e2ec0..3a50f55927afd22b84dd12e331b83960865a409a 100644 --- a/src/views/Authentication/ChangePasswordView.vue +++ b/src/views/Authentication/ChangePasswordView.vue @@ -60,7 +60,7 @@ const submitForm = async () => { try { const resetPassword = { password: newPassword.value, - token: token + token: token as string, }; const response = await UserService.confirmPasswordReset({ requestBody: resetPassword }); console.log(response); diff --git a/src/views/BasePageView.vue b/src/views/BasePageView.vue index a9780ec71399880d811a9690ddc028b96ec94d17..07af9953b1384c894b42a476b9bccecd9012526e 100644 --- a/src/views/BasePageView.vue +++ b/src/views/BasePageView.vue @@ -8,13 +8,13 @@ import Menu from '@/components/BaseComponents/Menu.vue' <Menu></Menu> <div style="display: flex; flex-direction: row;"> - <img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;"> + <img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;" alt="picture"> </div> <div> <RouterView /> </div> <div style="display: flex; flex-direction: row;"> - <img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;"> + <img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;" alt="picture"> </div> <Footer></Footer> </template> \ No newline at end of file diff --git a/src/views/BudgetOverview.vue b/src/views/BudgetOverview.vue index e58fb67ed304fcffc341f2baea40d1ace164c119..617c79bb0bf6084454c6ca61e8e8238cd8deea70 100644 --- a/src/views/BudgetOverview.vue +++ b/src/views/BudgetOverview.vue @@ -1,6 +1,9 @@ <script setup lang="ts"> import Button1 from '@/components/Buttons/Button1.vue' import BudgetBox from '@/components/Budget/BudgetBox.vue' + +const budget = 1000; +const expenses = 95600; </script> <template> @@ -19,15 +22,15 @@ import BudgetBox from '@/components/Budget/BudgetBox.vue' <!--TODO make this more generic--> <ul class="budgetContainer"> - <li><budget-box title="April 2024" budget="1000" expenses="908700"></budget-box></li> - <li><budget-box title="Mai 2024" budget="1000" expenses="87"></budget-box></li> - <li><budget-box title="Juni 2024" budget="1000" expenses="87"></budget-box></li> - <li><budget-box title="Juli 2024" budget="1000" expenses="87"></budget-box></li> - <li><budget-box title="August 2024" budget="1000" expenses="87"></budget-box></li> - <li><budget-box title="September 2024" budget="1000" expenses="87"></budget-box></li> - <li><budget-box title="Oktober 2024" budget="1000" expenses="87"></budget-box></li> - <li><budget-box title="November 2024" budget="1000" expenses="87"></budget-box></li> - <li><budget-box title="Desember 2024" budget="1000" expenses="87"></budget-box></li> + <li><budget-box title="April 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="Mai 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="Juni 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="Juli 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="August 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="September 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="Oktober 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="November 2024" :budget=budget :expenses=expenses></budget-box></li> + <li><budget-box title="Desember 2024" :budget=budget :expenses=expenses></budget-box></li> </ul> <nav id="navbar" aria-label="Page navigation example"> diff --git a/src/views/BudgetView.vue b/src/views/BudgetView.vue index 0297c102ccddc3c1f463cf93fb3049b5f1901b1c..750d0e16a3140ba26aee608bf5c1d77c609d78a1 100644 --- a/src/views/BudgetView.vue +++ b/src/views/BudgetView.vue @@ -153,7 +153,7 @@ const onDeleteBudgetPressed = () => { <button class="btn btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> - <button id="importButton" class="btn btn-primary"><img src="../assets/icons/import.svg" height="20" width="20">Import budget</button> + <button id="importButton" class="btn btn-primary"><img src="../assets/icons/import.svg" height="20" width="20" alt="picture">Import budget</button> <button id="editBudget" class="btn btn-primary" data-bs-toggle="collapse" data-bs-target="#editBudgetCollapse" aria-expanded="false" aria-controls="editBudgetCollapse"><img src="../assets/icons/edit-button.svg" alt="editButton">Rename budget</button> <div class="collapse" id="editBudgetCollapse"> <div class="container collapse-container"> @@ -165,7 +165,7 @@ const onDeleteBudgetPressed = () => { </form> </div> </div> - <button id="deleteButton" class="btn btn-primary" data-bs-toggle="modal" @click="onDeleteBudgetPressed"><img src="../assets/icons/trash-can.svg" height="20" width="20">Delete budget</button> + <button id="deleteButton" class="btn btn-primary" data-bs-toggle="modal" @click="onDeleteBudgetPressed"><img src="../assets/icons/trash-can.svg" height="20" width="20" alt="picture">Delete budget</button> </div> </div> </div> @@ -173,7 +173,7 @@ const onDeleteBudgetPressed = () => { <div class="budget-info-container"> <div class="info budget-container"> - <i><img src="../assets/icons/money2.svg" width="48px" height="48px"></i> + <i><img src="../assets/icons/money2.svg" width="48px" height="48px" alt="picture"></i> <div class="budget-text-container"> <h5>{{budget}} kr</h5> <p>Budget</p> @@ -181,7 +181,7 @@ const onDeleteBudgetPressed = () => { </div> <div class="info expenses-container"> - <i><img src="../assets/icons/credit-card.svg" width="48px" height="48px"></i> + <i><img src="../assets/icons/credit-card.svg" width="48px" height="48px" alt="picture"></i> <div class="expenses-text-container"> <h5>{{expenses}} kr</h5> <p>Expenses</p> @@ -189,7 +189,7 @@ const onDeleteBudgetPressed = () => { </div> <div class="info balance-container"> - <i ref="iRef"><img src="../assets/icons/scale.svg" width="48px" height="48px"></i> + <i ref="iRef"><img src="../assets/icons/scale.svg" width="48px" height="48px" alt="picture"></i> <div class="balance-text-container"> <h5>{{balance}} kr</h5> <p>Balance</p> diff --git a/src/views/ConfigurationView.vue b/src/views/ConfigurationView.vue index 58a63f43e9d6cb7ab5f205a8fb09489b9bd2701c..2c375e5d6c494d84822eb53e84684aba09572356 100644 --- a/src/views/ConfigurationView.vue +++ b/src/views/ConfigurationView.vue @@ -1,7 +1,5 @@ <script setup lang="ts"> import Configuration from '@/components/Configuration/Configuration.vue' -import Menu from '@/components/BaseComponents/Menu.vue' -import Footer from '@/components/BaseComponents/Footer.vue' </script> <template> diff --git a/src/views/LeaderboardView.vue b/src/views/LeaderboardView.vue index 8be05c6a348a0ecd3a1e295fcee44c0922cff104..12acc33fe8c791a95188ebdc829294b90752f25a 100644 --- a/src/views/LeaderboardView.vue +++ b/src/views/LeaderboardView.vue @@ -9,42 +9,38 @@ <div class="btn-group-vertical" id="radioContainer" role="group" aria-label="Vertical radio toggle button group"> <input type="radio" class="btn-check" name="vbtn-radio" id="vbtn-radio1" autocomplete="off" checked> - <label class="btn btn-outline-primary" for="vbtn-radio1" @click="global"><img src="@/assets/globe.png" style="width: 60px"> Global</label> + <label class="btn btn-outline-primary" for="vbtn-radio1" @click="global"><img src="@/assets/globe.png" style="width: 60px" alt="globe"> Global</label> <input type="radio" class="btn-check" name="vbtn-radio" id="vbtn-radio2" autocomplete="off"> - <label class="btn btn-outline-primary" for="vbtn-radio2" @click="friends"><img src="@/assets/friends.png" style="width: 60px"> Friends</label> + <label class="btn btn-outline-primary" for="vbtn-radio2" @click="friends"><img src="@/assets/friends.png" style="width: 60px" alt="friends"> Friends</label> </div> </div> </div> <main> <div id="leaderboard"> - <h1><img src="@/assets/items/pigcoin.png" style="width: 3rem"> Total points</h1> + <h1><img src="@/assets/items/pigcoin.png" style="width: 2rem" alt="pig coin"> Total points</h1> <Leaderboard :leaderboard="pointsLeaderboardData" :leaderboardExtra="pointsLeaderboardDataExtra" @navigateToUserProfile="navigateToUserProfile" /> </div> <div id="leaderboard"> - <h1><img src="@/assets/icons/fire.png" style="width: 2rem"> Current streak</h1> + <h1><img src="@/assets/icons/fire.png" style="width: 2rem" alt="fire"> Current streak</h1> <Leaderboard :leaderboard="currentLeaderboardData" :leaderboardExtra="currentLeaderboardDataExtra" @navigateToUserProfile="navigateToUserProfile" /> </div> <div id="leaderboard"> - <h1><img src="@/assets/icons/fire.png" style="width: 2rem"> Highest streak</h1> - let streakLeaderboardData = ref([] as LeaderboardEntryDTO[]); - let streakLeaderboardDataExtra = ref([] as LeaderboardEntryDTO[]); + <h1><img src="@/assets/icons/fire.png" style="width: 2rem" alt="fire"> Highest streak</h1> <Leaderboard :leaderboard="streakLeaderboardData" :leaderboardExtra="streakLeaderboardDataExtra" @navigateToUserProfile="navigateToUserProfile" /> </div> </main> </div> <div id="communityContainer"> <h1>Total points earned as a community</h1> - <h2>1000000 <img src="@/assets/items/v-buck.png" style="width: 2rem"></h2> + <h2>1000000 <img src="@/assets/items/v-buck.png" style="width: 2rem" alt="alt"></h2> </div> </template> <script setup lang="ts"> -import { onMounted, ref, type PropType } from 'vue'; -import { useRoute, useRouter } from 'vue-router'; +import { onMounted, ref } from 'vue'; +import { useRouter } from 'vue-router'; import Leaderboard from '@/components/LeaderboardComponents/Leaderboard.vue'; -import { on } from 'events'; import { LeaderboardService } from '@/api'; -import type { LeaderboardEntryDTO } from '@/api/models/LeaderboardEntryDTO'; let streakLeaderboardData = ref([] as any); let currentLeaderboardData = ref([] as any); @@ -57,7 +53,7 @@ let pointsLeaderboardDataExtra = ref([] as any); const router = useRouter(); async function fetchQuizData() { - global(); + await global(); } onMounted(() => { @@ -204,10 +200,4 @@ h1 { margin-bottom: 5rem; } -.leaderBoardButton { - padding: 1rem 4rem; - font-weight: 700; - border-radius: 2rem; - margin: 1rem; -} </style> \ No newline at end of file diff --git a/src/views/Settings/SettingsAccountView.vue b/src/views/Settings/SettingsAccountView.vue index f3d2c54bd951805dd072af5d700c661f52dec5f1..ee06249337fbba6a7b358a3cea9c5fb69d9d96ec 100644 --- a/src/views/Settings/SettingsAccountView.vue +++ b/src/views/Settings/SettingsAccountView.vue @@ -11,6 +11,14 @@ const confirmPasswordRef = ref('') const formRef = ref() let samePasswords = ref(true) +const handleFirstNameInputEvent = (newValue: any) => { + firstNameRef.value = newValue +} + +const handleEmailInputEvent = (newValue: any) => { + emailRef.value = newValue +} + </script> <template> diff --git a/src/views/Settings/SettingsNotificationView.vue b/src/views/Settings/SettingsNotificationView.vue index 233614f32b4d2ecf3d44920879666b16bf7b2628..225f1ae14d2fb1c26febea564ac1908461e9c4c1 100644 --- a/src/views/Settings/SettingsNotificationView.vue +++ b/src/views/Settings/SettingsNotificationView.vue @@ -8,12 +8,12 @@ <div class="small text-muted mb-3">Receive security alert notifications via email </div> <div class="custom-control custom-checkbox"> - <input type="checkbox" class="custom-control-input" id="customCheck1" checked=""> + <input type="checkbox" class="custom-control-input" id="customCheck1"> <label class="custom-control-label" for="customCheck1">Email each time a vulnerability is found</label> </div> <div class="custom-control custom-checkbox"> - <input type="checkbox" class="custom-control-input" id="customCheck2" checked=""> + <input type="checkbox" class="custom-control-input" id="customCheck2"> <label class="custom-control-label" for="customCheck2">Email a digest summary of vulnerability</label> </div> @@ -24,7 +24,7 @@ <li class="list-group-item has-icon"> Comments <div class="custom-control custom-control-nolabel custom-switch ml-auto"> - <input type="checkbox" class="custom-control-input" id="customSwitch1" checked=""> + <input type="checkbox" class="custom-control-input" id="customSwitch1"> <label class="custom-control-label" for="customSwitch1"></label> </div> </li> @@ -38,14 +38,14 @@ <li class="list-group-item has-icon"> Reminders <div class="custom-control custom-control-nolabel custom-switch ml-auto"> - <input type="checkbox" class="custom-control-input" id="customSwitch3" checked=""> + <input type="checkbox" class="custom-control-input" id="customSwitch3"> <label class="custom-control-label" for="customSwitch3"></label> </div> </li> <li class="list-group-item has-icon"> Events <div class="custom-control custom-control-nolabel custom-switch ml-auto"> - <input type="checkbox" class="custom-control-input" id="customSwitch4" checked=""> + <input type="checkbox" class="custom-control-input" id="customSwitch4"> <label class="custom-control-label" for="customSwitch4"></label> </div> </li> diff --git a/src/views/Settings/SettingsProfileView.vue b/src/views/Settings/SettingsProfileView.vue index e082b050b85b9654f1af815a952137422c235dc1..b562554ee44203d4f4b82ebfaa209d03c9b27ab9 100644 --- a/src/views/Settings/SettingsProfileView.vue +++ b/src/views/Settings/SettingsProfileView.vue @@ -11,6 +11,15 @@ const confirmPasswordRef = ref('') const formRef = ref() let samePasswords = ref(true) +const handleFirstNameInputEvent = (newValue: any) => { + firstNameRef.value = newValue +} + + +const handleSurnameInputEvent = (newValue: any) => { + surnameRef.value = newValue +} + </script> diff --git a/src/views/SettingsView.vue b/src/views/SettingsView.vue index 195694c4eb50a14a7eaabaa324c6876bd01b7e3d..bfacde14fc84fd679ba5dd74411c03c60bf5a219 100644 --- a/src/views/SettingsView.vue +++ b/src/views/SettingsView.vue @@ -116,7 +116,7 @@ function toBilling() { <div class="card-header border-bottom mb-3 d-flex d-md-none"> <ul class="nav nav-tabs card-header-tabs nav-gap-x-1" role="tablist"> <li class="nav-item"> - <a href="#profile" data-toggle="tab" class="nav-link has-icon active"><svg + <a href="#" data-toggle="tab" class="nav-link has-icon active"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user"> @@ -125,7 +125,7 @@ function toBilling() { </svg></a> </li> <li class="nav-item"> - <a href="#account" data-toggle="tab" class="nav-link has-icon"><svg + <a href="#" data-toggle="tab" class="nav-link has-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings"> @@ -136,7 +136,7 @@ function toBilling() { </svg></a> </li> <li class="nav-item"> - <a href="#security" data-toggle="tab" class="nav-link has-icon"><svg + <a href="#" data-toggle="tab" class="nav-link has-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shield"> @@ -144,7 +144,7 @@ function toBilling() { </svg></a> </li> <li class="nav-item"> - <a href="#notification" data-toggle="tab" class="nav-link has-icon"><svg + <a href="#" data-toggle="tab" class="nav-link has-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bell"> @@ -153,7 +153,7 @@ function toBilling() { </svg></a> </li> <li class="nav-item"> - <a href="#billing" data-toggle="tab" class="nav-link has-icon"><svg + <a href="#" data-toggle="tab" class="nav-link has-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-credit-card"> @@ -180,10 +180,6 @@ function toBilling() { margin-bottom: 4rem; } -.main-body { - padding: 15px; -} - .nav-link { color: #4a5568; } @@ -215,31 +211,13 @@ function toBilling() { margin-left: -8px; } -.gutters-sm>.col, -.gutters-sm>[class*=col-] { +.gutters-sm>, +.gutters-sm> { padding-right: 8px; padding-left: 8px; } -.mb-3, -.my-3 { +.mb-3 { margin-bottom: 1rem !important; } - -.bg-gray-300 { - background-color: #e2e8f0; -} - -.h-100 { - height: 100% !important; -} - -.shadow-none { - box-shadow: none !important; -} - -.routerLink { - text-decoration: none; - color: #4a5568; -} </style> \ No newline at end of file diff --git a/src/views/UnauthorizedView.vue b/src/views/UnauthorizedView.vue index 2e79554d2ddf9024e05cde67064b0d14533d611c..b5cc9b581ba5c25e50530d000ef516aa383a4eef 100644 --- a/src/views/UnauthorizedView.vue +++ b/src/views/UnauthorizedView.vue @@ -3,7 +3,7 @@ <div class="container py-5"> <div class="row"> <div class="col-md-2 text-center"> - <p><img src="@/assets/icons/danger.svg"> <br/>Status Code: 403</p> + <p><img src="@/assets/icons/danger.svg" alt="danger"> <br/>Status Code: 403</p> </div> <div class="col-md-10"> <h3>OPPSSS!!!! Sorry...</h3> @@ -16,7 +16,6 @@ </template> <script setup lang="ts"> -import { defineComponent } from 'vue'; import { useRouter } from 'vue-router'; import Button1 from '@/components/Buttons/Button1.vue'; @@ -30,6 +29,7 @@ const home = () => { <style scoped> body { - background-image: url('@/assets/401-error.jpg'); + background-image: url('@/assets/401-error.png'); } + </style> \ No newline at end of file diff --git a/src/views/User/UserFriendsView.vue b/src/views/User/UserFriendsView.vue index e281c65b25970f4e7e29ddf897a8696f8db9a64d..f37dfe4b237c2f8d9f20cc87c29973874f2ea33b 100644 --- a/src/views/User/UserFriendsView.vue +++ b/src/views/User/UserFriendsView.vue @@ -360,11 +360,11 @@ function addFriend() { } // Define the navigateToQuiz method -const navigateToFriend = (friendID :string) => { +const navigateToFriend = (friendID :number) => { router.push('/profile/' + friendID) }; -const removeFriend = (friendID) => { +const removeFriend = (friendID: number) => { }; diff --git a/tsconfig.json b/tsconfig.json index 5304731b8d26326f23e647245010b28216f91dac..90465d0f61a8a55de2be4e17f31c5c343c2fceaa 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,8 @@ } ], "compilerOptions": { - "module": "NodeNext" + "module": "NodeNext", + "types" : ["pinia-plugin-persist"], + "typeRoots": ["./node_modules/@types", "./node_modules/pinia-plugin-persist/dist"] } } diff --git a/types/form-data.d.ts b/types/form-data.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..e5597eeceadf947cc15dfda25a56f894e4e77963 --- /dev/null +++ b/types/form-data.d.ts @@ -0,0 +1 @@ +declare module 'form-data'; \ No newline at end of file