diff --git a/.eslintrc.js b/.eslintrc.js index b1e3f4cefc1bfcefbf35a01bf63d67d0b46da654..b741035b661134129a5b9b39c05ecfedc3d810b2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -13,6 +13,7 @@ module.exports = { }, rules: { "prettier/prettier": "warn", + "linebreak-style": 0, "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", }, diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 64226ef4d8cfb17bd806c1510b3063d28b96f959..a50b3b132633e6dddaf8a8c26664adf4f4d16277 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,56 +1,41 @@ -# This file is a template, and might need editing before it works on your project. -# To contribute improvements to CI/CD templates, please follow the Development guide at: -# https://docs.gitlab.com/ee/development/cicd/templates.html -# This specific template is located at: -# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml - -# This is a sample GitLab CI/CD configuration file that should run without any modifications. -# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts, -# it uses echo commands to simulate the pipeline execution. -# -# A pipeline is composed of independent jobs that run scripts, grouped into stages. -# Stages run in sequential order, but jobs within stages run in parallel. -# -# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages +image: node:16 -stages: # List of stages for jobs, and their order of execution - - build +stages: + - setup - test -image: node:16 +variables: + npm_config_cache: "$CI_PROJECT_DIR/.npm" -cache: - paths: - - node_modules/ - -install_dependencies_job: # This job runs in the build stage, which runs first. - stage: build +# Define a hidden job to be used with extends +# Better than default to avoid activating cache for all jobs +.dependencies_cache: + cache: + key: + files: + - package-lock.json + paths: + - .npm + policy: pull +setup: + stage: setup script: - - echo "Installing dependencies..." - - npm install - - echo "Dependencies installed." + - npm ci + extends: .dependencies_cache + cache: + policy: pull-push artifacts: + expire_in: 3 days #delete cache after 3 days to conserve space paths: - - node_modules/ + - node_modules - -lint-test-job: # This job also runs in the test stage. - stage: test # It can run at the same time as unit-test-job (in parallel). +lint_test: + stage: test script: - - echo "Linting the code..." - npm run lint - - echo "Code-linting complete." - artifacts: - paths: - - node_modules/ -unit-test-job: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. +unit_test: + stage: test script: - - echo "Running unit tests..." - - npm run test:unit -- --coverage - - echo "Unit tests complete." - artifacts: - paths: - - node_modules/ + - npm run test:unit diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index df36fcfb72584e00488330b560ebcf34a41c64c2..0000000000000000000000000000000000000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 41235286563508e0feb4c451a34b598ef822ec21..0000000000000000000000000000000000000000 --- a/public/index.html +++ /dev/null @@ -1,17 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width,initial-scale=1.0"> - <link rel="icon" href="<%= BASE_URL %>favicon.ico"> - <title><%= htmlWebpackPlugin.options.title %></title> - </head> - <body> - <noscript> - <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> - </noscript> - <div id="app"></div> - <!-- built files will be auto injected --> - </body> -</html> diff --git a/src/App.vue b/src/App.vue index 92ede030b9b5c47a3f4aeec86c1c578464e12f26..28f284a38653ef90ffb4d65080f1b559b8d09ca1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,7 +1,7 @@ <template> <div> - <NavBar /> - <router-view /> + <NavBar /> + <router-view /> </div> </template> @@ -19,4 +19,4 @@ export default defineComponent({ NavBar, }, }); -</script> \ No newline at end of file +</script> diff --git a/src/assets/additem.png b/src/assets/additem.png new file mode 100644 index 0000000000000000000000000000000000000000..6eed86737785b8a2425d33de3c613cfb7832b041 Binary files /dev/null and b/src/assets/additem.png differ diff --git a/src/assets/messages.png b/src/assets/messages.png new file mode 100644 index 0000000000000000000000000000000000000000..b8c15889efc747b700220ca819b2c12caa09e780 Binary files /dev/null and b/src/assets/messages.png differ diff --git a/src/assets/notifications.png b/src/assets/notifications.png new file mode 100644 index 0000000000000000000000000000000000000000..a612605af4bc91be42f5989632fb3287aac7bbfd Binary files /dev/null and b/src/assets/notifications.png differ diff --git a/src/assets/profile.png b/src/assets/profile.png new file mode 100644 index 0000000000000000000000000000000000000000..79b3e5f3624b8db0593ca77997f52633c34f7de9 Binary files /dev/null and b/src/assets/profile.png differ diff --git a/src/components/AddNewItem.vue b/src/components/AddNewItem.vue index cfe5ea645bcbfd2cff19a9a68d46499547f45e4c..9324b2bb76cfe0df33fde7a0cad06bd202470708 100644 --- a/src/components/AddNewItem.vue +++ b/src/components/AddNewItem.vue @@ -68,6 +68,40 @@ </div> </div> + <!-- Select Group --> + <div class="mb-6"> + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + >Gruppe</label + > + <select + v-model="v$.item.selectGroup.$model" + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + > + <option class="text-gray-400" value="" disabled selected> + Select a Group + </option> + <option + v-for="group in groups" + :key="group" + class="text-gray-900 text-sm" + > + {{ group }} + </option> + </select> + + <!-- error message for select box --> + <div + class="text-red" + v-for="(error, index) of v$.item.selectGroup.$errors" + :key="index" + > + <div class="text-red-600 text-sm"> + {{ error.$message }} + </div> + </div> + </div> + <!-- price --> <div class="mb-6" :class="{ error: v$.item.price.$errors.length }"> <label @@ -122,6 +156,32 @@ </div> </div> + <!-- Address --> + <div class="mb-6" :class="{ error: v$.item.address.$errors.length }"> + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + >Adresse</label + > + <input + type="text" + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="v$.item.address.$model" + id="adress" + required + /> + + <!-- error message for address--> + <div + class="text-red" + v-for="(error, index) of v$.item.address.$errors" + :key="index" + > + <div class="text-red-600 text-sm"> + {{ error.$message }} + </div> + </div> + </div> + <!-- Images --> <div> <label @@ -167,6 +227,9 @@ <script> import useVuelidate from "@vuelidate/core"; +import { parseUserFromToken } from "@/utils/token-utils"; +import { postNewItem } from "@/utils/apiutil"; + import { required, helpers, @@ -186,14 +249,20 @@ export default { return { item: { title: { - required, + required: helpers.withMessage( + () => "Tittelen kan ikke være tom", + required + ), max: helpers.withMessage( () => `Tittelen kan inneholde max 50 tegn`, maxLength(50) ), }, description: { - required, + required: helpers.withMessage( + () => "Beskrivelsen kan ikke være tom", + required + ), max: helpers.withMessage( () => `Beskrivelsen kan inneholde max 200 tegn`, maxLength(200) @@ -213,6 +282,19 @@ export default { select: { required: helpers.withMessage(() => `Velg en kategori`, required), }, + selectGroup: { + required: helpers.withMessage(() => `Velg en gruppe`, required), + }, + address: { + required: helpers.withMessage( + () => "Addressen kan ikke være tom", + required + ), + max: helpers.withMessage( + () => `Addressen kan inneholde max 50 tegn`, + maxLength(50) + ), + }, }, }; }, @@ -222,14 +304,18 @@ export default { item: { title: "", description: "", + address: "", price: "", category: "", select: null, type: "", images: [], + userId: -1, + selectGroup: null, }, //Kategorier skal legges inn ved api/hente fra db, her må det endres etterhvert categories: ["Hage", "Kjøkken", "Musikk", "Annet"], + groups: [4040, 4041], }; }, methods: { @@ -251,14 +337,41 @@ export default { if (this.checkValidation()) { console.log("validert, videre..."); + + this.checkUser(); + console.log("Tittel: " + this.item.title); console.log("Kategori: " + this.item.select); console.log("Beskrivelse: " + this.item.description); + console.log("Addressen: " + this.item.address); console.log("Pris: " + this.item.price); console.log("bilder: " + this.item.images); + console.log("gruppe: " + this.item.selectGroup); + + const itemInfo = { + title: this.item.title, + description: this.item.description, + pricePerDay: this.item.price, + address: this.item.address, + userID: this.item.userId, + categoryNames: [], + communityIDs: [this.item.selectGroup], + }; + + console.log(itemInfo); + + const postRequest = await postNewItem(itemInfo); + + console.log("posted: " + postRequest); } }, + checkUser: async function () { + let user = parseUserFromToken(this.$store.state.user.token); + this.item.userId = parseInt(user.accountId); + console.log("id: " + this.item.userId); + }, + addImage: function (event) { console.log(event.target.files); this.item.images.push(URL.createObjectURL(event.target.files[0])); diff --git a/src/components/CreateNewGroup.vue b/src/components/CreateNewGroup.vue index ceb5303249f9797e27e06fea8c189f9ab99a095f..d3df1b3ebc3cf521e1700a0eec577594aa8d802a 100644 --- a/src/components/CreateNewGroup.vue +++ b/src/components/CreateNewGroup.vue @@ -76,6 +76,31 @@ </div> </div> + <!-- Place --> + <div class="mt-6" :class="{ error: v$.group.place.$errors.length }"> + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + >By/Sted</label + > + <input + type="text" + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="v$.group.place.$model" + required + /> + + <!-- error message for place--> + <div + class="text-red" + v-for="(error, index) of v$.group.place.$errors" + :key="index" + > + <div class="text-red-600 text-sm"> + {{ error.$message }} + </div> + </div> + </div> + <!-- Select category --> <div class="mt-6"> <label @@ -199,6 +224,7 @@ <script> import useVuelidate from "@vuelidate/core"; import { required, helpers, maxLength } from "@vuelidate/validators"; +import { postNewgroup } from "@/utils/apiutil"; export default { name: "CreateNewGroup.vue", @@ -220,6 +246,16 @@ export default { maxLength(50) ), }, + place: { + required: helpers.withMessage( + () => "Stedsnavn kan ikke være tom", + required + ), + max: helpers.withMessage( + () => `Stednavn kan være på max 50 tegn`, + maxLength(50) + ), + }, description: { required: helpers.withMessage( () => "Beskrivelsen kan ikke være tom", @@ -245,6 +281,8 @@ export default { images: [], categories: ["Borettslag", "Idrettsklubb", "Fritidsklubb"], radio: null, + place: "", + visibility: 1, }, imageThere: false, }; @@ -267,6 +305,14 @@ export default { checkRadioButton: function (event) { this.group.radio = event.target.value; console.log(this.group.radio); + + if (this.group.radio == null || this.group.radio == "Åpen") { + this.group.visibility = 1; + } else { + this.group.visibility = 0; + } + + console.log("visibility: " + this.group.visibility); }, checkValidation: function () { console.log("sjekker validering"); @@ -287,11 +333,26 @@ export default { if (this.checkValidation()) { console.log("validert, videre..."); console.log("Navn: " + this.group.name); + console.log("Sted: " + this.group.place); console.log("Synlighet: " + this.group.radio); console.log("Kategori: " + this.group.select); console.log("Beskrivelse: " + this.group.description); console.log("bilder: " + this.group.images); + + const groupInfo = { + name: this.group.name, + description: this.group.description, + visibility: this.group.visibility, + location: this.group.place, + picture: "", + }; + + console.log(groupInfo); + const postCreatedGroup = await postNewgroup(groupInfo); + console.log(postCreatedGroup); } + + }, addImage: function (event) { @@ -301,6 +362,6 @@ export default { this.imageThere = true; console.log("image: " + this.imageThere); }, - }, + } }; </script> diff --git a/src/components/HelloWorld.vue b/src/components/HomeComponent.vue similarity index 76% rename from src/components/HelloWorld.vue rename to src/components/HomeComponent.vue index 4ca942e95518328dbd676a222c03804175e93dd2..d2c20ac82db8c41b7ff98f008f5acc328ac4d5ae 100644 --- a/src/components/HelloWorld.vue +++ b/src/components/HomeComponent.vue @@ -6,21 +6,20 @@ <router-link to="/about" class="m-6">Om BoCo</router-link> -<div @click="logout" class="m-6 cursor-pointer"><p>Logout</p></div> - + <div @click="logout" class="m-6 cursor-pointer"><p>Logout</p></div> </div> </template> <script> export default { - name: "HelloWorld", + name: "HomeComponent", data: () => ({}), methods: { - logout (){ + logout() { this.$store.commit("logout"); }, - } + }, }; </script> diff --git a/src/components/LoginForm.vue b/src/components/LoginForm.vue index e4b0c39207cd58cdc20c68281aee6c505519b012..b34550fd029967e4ea8c7215863454ee891102de 100644 --- a/src/components/LoginForm.vue +++ b/src/components/LoginForm.vue @@ -1,9 +1,8 @@ <template> - <div class="App"> - <div id="logoField" class="flex justify-center m-6"> - <img src="../assets/logo3.svg" alt="BoCo logo" /> - </div> + <div class="max-w-md p-6 mx-auto rounded-md shadow-lg mt-16"> + + <div class="flex justify-center text-2xl ">Logg inn</div> <div id="emailField" class="m-6" @@ -49,7 +48,7 @@ <input type="password" id="password" - class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 " v-model="v$.user.password.$model" required @keyup.enter="loginClicked" @@ -73,20 +72,20 @@ <div id="buttonsField" class="m-6"> <div class="align-items: flex-end; mb-6"> <div class="ml-3 text-sm"> - <router-link to="about" class="text-blue-600" + <router-link to="/resetPassword" class="text-blue-600 flex justify-end" >Glemt passord</router-link > </div> </div> <button @click="loginClicked" - class="flex justify-center align-items: flex-end; text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" + class="w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5" > Logg inn </button> - <div class="align-items: flex-end; mb-6 mt-6"> - <div class="ml-3 text-sm"> - <router-link to="register" class="text-blue-600" + <div class="align-items: flex-end; mb-6 mt-12"> + <div class="text-sm"> + <router-link to="register" class="text-blue-600 flex justify-center" >Ny bruker</router-link > </div> @@ -102,7 +101,6 @@ import useVuelidate from "@vuelidate/core"; import { required, email, helpers } from "@vuelidate/validators"; import { doLogin } from "@/utils/apiutil"; -import { parseUserFromToken } from "@/utils/token-utils"; export default { name: "LoginForm.vue", @@ -110,7 +108,6 @@ export default { setup() { return { v$: useVuelidate() }; }, - validations() { return { user: { @@ -160,12 +157,7 @@ export default { this.$store.commit("logout"); } else if (loginResponse.isLoggedIn === true) { this.$store.commit("saveToken", loginResponse.token); - - let user = parseUserFromToken(loginResponse.token); - console.log(user); - let id = user.accountId; - console.log(id); - await this.$router.push("/profile/" + id); + await this.$router.push("/"); } else { console.log("Something went wrong"); } diff --git a/src/components/MemberList.vue b/src/components/MemberList.vue new file mode 100644 index 0000000000000000000000000000000000000000..5f935be3e67737b6228cc4113fc0da6a8bb8a934 --- /dev/null +++ b/src/components/MemberList.vue @@ -0,0 +1,36 @@ +<template> + <ul> + <li v-for="member in memberlist" :key="member.userId"> + <user-list-item-card :admin="admin" :user="member" /> + </li> + </ul> +</template> + +<script> +import UserListItemCard from "./UserProfileComponents/UserListItemCard.vue"; + +export default { + data() { + return { + memberlist: [ + { + userId: 2, + firstName: "erik", + lastName: "hansen", + }, + { + userId: 1, + firstName: "Test", + lastName: "Testesen", + }, + ], + }; + }, + components: { + UserListItemCard, + }, + props: { + admin: Boolean, + }, +}; +</script> diff --git a/src/components/MessagesForm.vue b/src/components/MessagesForm.vue index 9c68c2f297cfd7e9b8695f64a51f0796b221ce85..5e1113cc8e9a323a57c3116713f7e0f92a3b1774 100644 --- a/src/components/MessagesForm.vue +++ b/src/components/MessagesForm.vue @@ -1,13 +1,11 @@ <template> - <div> This is a message page</div> + <div>This is a message page</div> </template> <script> export default { - name: "MessagesForm" -} + name: "MessagesForm", +}; </script> -<style scoped> - -</style> \ No newline at end of file +<style scoped></style> diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 978e645fefa885e1dfe8fe775303d6ce7ce98983..d195ae22c1d8fab5e9fdbb11b938adb3f36a9f7a 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -1,65 +1,62 @@ <template> - <nav class="flex items-center justify-between bg-white h-20 shadow-2xl"> + <nav class="flex items-center justify-between bg-white h-20 border-1 border-b border-gray-300 border-solid"> <div class="logo"> - <img class="ml-4 cursor-pointer h-16 " src="../assets/logo3.svg" alt="BoCo logo" @click="$router.push('/')"/> + <img + class="m-2 cursor-pointer h-16" + src="../assets/logo3.svg" + alt="BoCo logo" + @click="$router.push('/')" + /> </div> <ul class="flex"> <li> - <div class="text-black mr-4 bg-gray-100 p-1 hover:bg-gray-600 transition-all rounded" @click="loadMessages">Meldinger</div> + <img + class="m-6 cursor-pointer h-8" + src="../assets/additem.png" + alt="Legg til" + @click="$router.push('/addNewItem')" + /> </li> <li> - <div class="text-black mr-4 bg-gray-100 p-1 hover:bg-gray-600 transition-all rounded" @click="loadNotifications">Varsler</div> + <img + class="m-6 cursor-pointer h-8" + src="../assets/messages.png" + alt="Meldinger" + @click="$router.push('/messages')" + /> </li> <li> - <div class="text-black mr-4 bg-gray-100 p-1 hover:bg-gray-600 transition-all rounded" @click="loadProfile">Profil</div> + <img + class="m-6 cursor-pointer h-8" + src="../assets/profile.png" + alt="Profil" + @click="loadProfile" + /> </li> </ul> </nav> </template> <script> -import {parseUserFromToken} from "@/utils/token-utils"; +import { parseUserFromToken } from "@/utils/token-utils"; export default { name: "NavBar.vue", methods: { - async loadMessages(){ - if(this.$store.state.user.token !== null){ - await this.$router.push("/messages") - } - else { - await this.$router.push("/login"); - } - - }, - async loadNotifications(){ - if(this.$store.state.user.token !== null){ - await this.$router.push("/notifications") - } - else { - await this.$router.push("/login"); - } - - }, async loadProfile() { - if(this.$store.state.user.token !== null){ - let user = parseUserFromToken(this.$store.state.user.token); - console.log(user); - let id = user.accountId; - console.log(id); - await this.$router.push("/profile/" + id); - } - else { + if (this.$store.state.user.token !== null) { + let user = parseUserFromToken(this.$store.state.user.token); + console.log(user); + let id = user.accountId; + console.log(id); + await this.$router.push("/profile/" + id); + } else { await this.$router.push("/login"); } - } - } -} - - + }, + }, +}; </script> -<style scoped> - -</style> \ No newline at end of file +<style scoped></style> diff --git a/src/components/NewPasswordForm.vue b/src/components/NewPasswordForm.vue index bff124848b1414094f2d52426ae9be5a10958b72..b314d10ce28bb0e84f8f52977a384147104edd0a 100644 --- a/src/components/NewPasswordForm.vue +++ b/src/components/NewPasswordForm.vue @@ -1,31 +1,28 @@ <template> <div - class="w-full max-w-sm p-6 m-auto bg-white rounded-md shadow-md dark:bg-gray-800" + class="w-full max-w-sm p-6 m-auto bg-white rounded-md shadow-md dark:bg-gray-800 mt-8 " > - <div id="logoField" class="flex justify-center m-6"> - <img src="../assets/logo3.svg" alt="BoCo logo" /> - </div> <div - id="firstPasswordField" - :class="{ error: v$.user.password.$errors.length }" + id="firstPasswordField" + :class="{ error: v$.user.password.$errors.length }" > <label - for="password" - class="block text-sm text-gray-800 dark:text-gray-200" - >Nytt passord</label + for="password" + class="block text-sm text-gray-800 dark:text-gray-200" + >Nytt passord</label > <input - type="password" - v-model="v$.user.password.$model" - class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40" + type="password" + v-model="v$.user.password.$model" + class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40" /> <!-- error message --> <div v-for="(error, index) of v$.user.password.$errors" :key="index"> <div - class="text-red-600 text-sm" - v-show="showError" - id="passwordErrorId" + class="text-red-600 text-sm" + v-show="showError" + id="passwordErrorId" > {{ error.$message }} </div> @@ -33,29 +30,29 @@ </div> <div - id="secondPasswordField" - class="mt-4" - :class="{ error: v$.user.rePassword.$errors.length }" + id="secondPasswordField" + class="mt-4" + :class="{ error: v$.user.rePassword.$errors.length }" > <div class="flex items-center justify-between"> <label - for="rePassword" - class="block text-sm text-gray-800 dark:text-gray-200" - >Gjenta nytt passord</label + for="rePassword" + class="block text-sm text-gray-800 dark:text-gray-200" + >Gjenta nytt passord</label > </div> <input - type="password" - v-model="v$.user.rePassword.$model" - class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40" + type="password" + v-model="v$.user.rePassword.$model" + class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40" /> <!-- error message --> <div v-for="(error, index) of v$.user.rePassword.$errors" :key="index"> <div - class="text-red-600 text-sm" - v-show="showError" - id="rePasswordErrorId" + class="text-red-600 text-sm" + v-show="showError" + id="rePasswordErrorId" > {{ error.$message }} </div> @@ -64,8 +61,8 @@ <div id="buttonsField" class="mt-6"> <button - @click="setNewPassword" - class="w-full px-4 py-2 tracking-wide text-white transition-colors duration-200 transform bg-gray-700 rounded-md hover:bg-gray-600 focus:outline-none focus:bg-gray-600" + @click="setNewPassword" + class="w-full px-4 py-2 tracking-wide text-white transition-colors duration-200 transform bg-gray-700 rounded-md hover:bg-gray-600 focus:outline-none focus:bg-gray-600" > Endre passord </button> diff --git a/src/components/NotificationsForm.vue b/src/components/NotificationsForm.vue index 27879f0e9b0fde81f074647cbbc6c9a7092c936d..b142fb2a8e36ec57b52256194cc35de433f71d63 100644 --- a/src/components/NotificationsForm.vue +++ b/src/components/NotificationsForm.vue @@ -1,13 +1,11 @@ <template> -<div> This is a notification page</div> + <div>This is a notification page</div> </template> <script> export default { - name: "NotificationsForm" -} + name: "NotificationsForm", +}; </script> -<style scoped> - -</style> \ No newline at end of file +<style scoped></style> diff --git a/src/components/ResetPassword.vue b/src/components/ResetPassword.vue new file mode 100644 index 0000000000000000000000000000000000000000..fa75650e93ef002ca97c3eebe85a567c0581efa4 --- /dev/null +++ b/src/components/ResetPassword.vue @@ -0,0 +1,84 @@ +<template> + <div class="resetPassword"> + <div + id="emailField" + class="m-6" + :class="{ error: v$.email.$errors.length }" + > + <div class="mb-6"> + <label + for="email" + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + >E-post</label + > + <input + type="email" + id="email" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + placeholder="eksempel@eksempel.no" + v-model="v$.email.$model" + required + /> + <!-- error message --> + <div v-for="(error, index) of v$.email.$errors" :key="index"> + <div + class="text-red-600 text-sm" + v-show="showError" + id="emailErrorId" + > + {{ error.$message }} + </div> + </div> + </div> + </div> + <button + @click="sendHome" + class="flex justify-center align-items: flex-end; text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" + > + Send e-post + </button> + </div> +</template> + +<script> +import useVuelidate from "@vuelidate/core"; +import { required, email, helpers } from "@vuelidate/validators"; +export default { + name: "ResetPassword.vue", + + data() { + return { + showError: false, + email: "", + }; + }, + setup() { + return { v$: useVuelidate() }; + }, + validations() { + return { + email: { + required, + email: helpers.withMessage(`E-posten er ugyldig`, email), + }, + }; + }, + methods: { + sendHome() { + this.showError = true; + + this.v$.email.$touch(); + + if (this.v$.email.$invalid) { + console.log("Ugyldig, avslutter..."); + return; + } else { + this.$router.push("/"); + } + }, + }, + validate() { + this.$refs.form.validate(); + }, +}; +</script> diff --git a/src/components/UserProfileComponents/LargeProfileCard.vue b/src/components/UserProfileComponents/LargeProfileCard.vue index 7c5c036f8103be9c42b62d0c818dfa229af2f8cd..f8ec7c083c839b58825a4e0e5ac9e7222bc99b21 100644 --- a/src/components/UserProfileComponents/LargeProfileCard.vue +++ b/src/components/UserProfileComponents/LargeProfileCard.vue @@ -1,13 +1,13 @@ <template> <div - class="max-w-sm bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700" + class="min-w-full md:min-w-0 md:w-96 my-4 py-8 bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700" > - <div v-show="isCurrentUser" class="flex justify-end px-4 pt-4"> + <div v-show="isCurrentUser" class="flex absolute justify-end px-4 pt-4"> <button id="dropdownDefault" data-dropdown-toggle="dropdown" @click="dropdown = !dropdown" - class="hidden sm:inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-1.5" + class="w-10 h-10 text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-1.5" type="button" > <svg @@ -25,7 +25,6 @@ <div id="dropdown" v-show="dropdown" - zindex="2" class="z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700" > <ul class="py-1" aria-labelledby="dropdownDefault"> @@ -50,6 +49,13 @@ >Leiehistorikk</router-link > </li> + <li> + <div + @click="logout" + class="cursor-pointer block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" + >Logg ut + </div> + </li> <li> <router-link to="/newPassword" @@ -67,6 +73,7 @@ </ul> </div> </div> + <div class="flex flex-col items-center pb-10"> <img class="mb-3 w-24 h-24 rounded-full shadow-lg" @@ -95,8 +102,7 @@ <script> import RatingComponent from "@/components/UserProfileComponents/RatingComponent.vue"; import { parseCurrentUser } from "@/utils/token-utils"; -import { getUser, getRenterRating, getOwnerRating } from "@/utils/apiutil"; -import router from "@/router"; +import { getUser, getAverageRating } from "@/utils/apiutil"; export default { name: "LargeProfileCard", @@ -106,8 +112,8 @@ export default { currentUser: {}, id: -1, isCurrentUser: false, - renterRating: -1, //getRenterRating(this.userID), - ownerRating: -1, //getOwnerRating(this.userID), + renterRating: -1, + ownerRating: -1, dropdown: false, }; }, @@ -116,23 +122,31 @@ export default { }, methods: { async getUser() { - this.currentUser = parseCurrentUser(); - this.id = router.currentRoute.value.params.id; - if (this.id == this.currentUser.account_id) { + this.currentUser = await parseCurrentUser(); + this.id = await this.$router.currentRoute.value.params.id; + + if (this.id === this.currentUser.accountId) { this.isCurrentUser = true; this.user = this.currentUser; return; } this.user = await getUser(this.id); - this.renterRating = getRenterRating(this.id); - this.ownerRating = getOwnerRating(this.id); + let rating = await getAverageRating(this.id); + if (rating >= 0 && rating <= 5) { + this.renterRating = rating; + this.ownerRating = rating; + } }, getProfilePicture() { - /* if (this.user.picture != "") { + if (this.user.picture !== "") { return this.user.picture; - } */ + } return "../assets/defaultUserProfileImage.jpg"; }, + logout(){ + this.$store.commit('logout'); + this.$router.push('/') + } }, beforeMount() { this.getUser(); diff --git a/src/components/UserProfileComponents/RatingComponent.vue b/src/components/UserProfileComponents/RatingComponent.vue index 662b9607911697c89421e7c4727b44caa93dfe4c..c6e7e8252f2fb8916098f3a1ab8b6a2a7290eb62 100644 --- a/src/components/UserProfileComponents/RatingComponent.vue +++ b/src/components/UserProfileComponents/RatingComponent.vue @@ -1,5 +1,5 @@ <template> - <ul v-if="compRating != -1" class="flex justify-center"> + <ul v-if="rating != -1" class="flex justify-center"> <li> <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400"> {{ ratingType }}: @@ -19,7 +19,7 @@ </li> <li> <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400"> - {{ compRating }} out of 5 + {{ rating }} out of 5 </p> </li> </ul> @@ -40,11 +40,6 @@ <script> export default { name: "RatingComponent", - data() { - return { - compRating: this.rating + 0, - }; - }, props: { rating: Number, ratingType: String, diff --git a/src/components/UserProfileComponents/UserListItemCard.vue b/src/components/UserProfileComponents/UserListItemCard.vue index 4da140e21610587c8e88953ed9b17572c9bef98a..005646d51d405772521392a452dc100e3ff75375 100644 --- a/src/components/UserProfileComponents/UserListItemCard.vue +++ b/src/components/UserProfileComponents/UserListItemCard.vue @@ -1,20 +1,31 @@ <template> <div - class="select-none cursor-pointer hover:bg-gray-50 flex flex-1 items-center p-4" + class="bg-white shadow dark:bg-gray-800 select-none cursor-pointer hover:bg-gray-50 flex items-center p-4" > - <div class="flex flex-col w-10 h-10 justify-center items-center mr-4"> - <router-link to=""> - <img alt="profil" :src="getProfilePicture" /> + <div class="h-10 w-10 flex flex-col justify-center items-center mr-4"> + <router-link :to="'/profile/' + user.userId"> + <img alt="profil" src="../../assets/defaultUserProfileImage.jpg" /> </router-link> </div> <div class="flex-1 pl-1"> <div class="font-medium dark:text-white"> - {{ user.first_name }} {{ user.last_name }} + {{ user.firstName }} {{ user.lastName }} </div> </div> + <div class="hidden md:block flex-auto"> + <rating-component :rating="rating" :ratingType="'Gjennomsnitts rating'" /> + </div> <div class="flex flex-row justify-center"> - <button class="w-10 text-right flex justify-end">Åpne chat</button> - <button v-if="admin" class="w-10 text-right flex justify-end"> + <button + v-if="!admin" + class="px-4 py-2 font-medium tracking-wide text-white capitalize transition-colors duration-200 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80" + > + Åpne chat + </button> + <button + v-if="admin" + class="px-4 py-2 font-medium tracking-wide text-white capitalize transition-colors duration-200 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80" + > Fjern bruker </button> </div> @@ -22,8 +33,19 @@ </template> <script> +import { getAverageRating } from "@/utils/apiutil"; +import RatingComponent from "./RatingComponent.vue"; + export default { name: "UserListItem", + data() { + return { + rating: this.getRating(), + }; + }, + components: { + RatingComponent, + }, props: { user: Object, admin: Boolean, @@ -35,6 +57,12 @@ export default { } return "../assets/defaultUserProfileImage.jpg"; }, + async getRating() { + this.rating = await getAverageRating(this.user.userId); + }, + }, + beforeMount() { + this.getRating(); }, }; </script> diff --git a/src/router/index.js b/src/router/index.js index 4c7ab2f8e919cf03089b93ee6da0618a4102676a..b10f877e9550493e48673fcf3ad54f5215406dcc 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -12,8 +12,7 @@ function guardRoute(to, from, next) { let isAuthenticated = store.state.user.token != null; if (isAuthenticated) { next(); // allow to enter route - } - else { + } else { next("/login"); // go to '/login'; } } @@ -62,10 +61,20 @@ const routes = [ name: "searchItemList", component: () => import("../views/SearchItemListView.vue"), }, + { + path: "/resetPassword", + name: "resetPassword", + component: () => import("../views/ResetPasswordView.vue"), + }, { path: "/createNewGroup", name: "createNewGroup", component: () => import("../views/CreateNewGroupView.vue"), + }, + { + path: "/group/:id/memberlist", + name: "memberlist", + component: () => import("../views/MemberListView.vue"), beforeEnter: guardRoute, }, { @@ -86,7 +95,6 @@ const routes = [ component: () => import("../views/MessagesView.vue"), beforeEnter: guardRoute, }, - ]; const router = createRouter({ diff --git a/src/utils/apiutil.js b/src/utils/apiutil.js index b31c432de7a80f9a1fc43a80975437cf9a736fe0..ed6731ef5796315cf802272b68d5f00d6dded1f2 100644 --- a/src/utils/apiutil.js +++ b/src/utils/apiutil.js @@ -72,12 +72,52 @@ export function getOwnerRating(userid) { }); } -export function doNewPassword() { //m - //add newPasswordInfo to input - const auth = { newPasswordSet: false }; - //return axios - //.post(API_URL + "newPassword", newPasswordInfo) - //.then((response) => {auth.newPasswordSet = true;return auth;}) - //.catch((error) => {console.log(error);return auth;}); - return auth; //remove after axios is added +export function getAverageRating(userid) { + return axios + .get(API_URL + "rating/" + userid + "/average", { + headers: tokenHeader(), + }) + .then((response) => { + return response.data; + }) + .catch((error) => { + console.error(error); + }); +} +export function doNewPassword() { + //m + //add newPasswordInfo to input + const auth = { newPasswordSet: false }; + //return axios + //.post(API_URL + "newPassword", newPasswordInfo) + //.then((response) => {auth.newPasswordSet = true;return auth;}) + //.catch((error) => {console.log(error);return auth;}); + return auth; //remove after axios is added +} + +export function postNewItem(itemInfo) { + return axios + .post(API_URL + "listing", itemInfo, { + headers: tokenHeader(), + }) + .then((response) => { + console.log("poster: " + response.data); + return response; + }) + .catch((error) => { + console.log(error.response); + return error; + }); +} + +export function postNewgroup(groupInfo) { + return axios + .post(API_URL + "communities/create", groupInfo, { headers: tokenHeader() }) + .then((response) => { + return response; + }) + .catch((error) => { + console.log(error.response); + return error; + }); } diff --git a/src/utils/token-utils.js b/src/utils/token-utils.js index ba37787fbb3f43cfdce7ba11aba70d2d3c8b5bff..6fd096d0bf94afeed0d7a77aa43d6fdf6417e757 100644 --- a/src/utils/token-utils.js +++ b/src/utils/token-utils.js @@ -3,7 +3,7 @@ import store from "@/store"; export function tokenHeader() { let token = store.state.user.token; - return { Authorization: token }; + return { Authorization: "Bearer " + token }; } export function parseCurrentUser() { diff --git a/src/views/AboutView.vue b/src/views/AboutView.vue index 4a2673ce0bceb9e56c7cfee50dd763d5cdea5a42..989873b7af72325c07d6100a5361faf0177a988d 100644 --- a/src/views/AboutView.vue +++ b/src/views/AboutView.vue @@ -10,7 +10,6 @@ import { defineComponent } from "vue"; export default defineComponent({ name: "HomeView", - components: { - }, + components: {}, }); </script> diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 79f6be96c7428c53aee6102577b49ec7c39715d5..37bac275afe04e62a533e8a63e05db38869d2097 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -1,18 +1,18 @@ <template> - <HelloWorld /> + <Home /> </template> <script> import { defineComponent } from "vue"; // Components -import HelloWorld from "../components/HelloWorld.vue"; +import Home from "../components/HomeComponent.vue"; export default defineComponent({ name: "HomeView", components: { - HelloWorld, + Home, }, }); </script> diff --git a/src/views/MemberListView.vue b/src/views/MemberListView.vue new file mode 100644 index 0000000000000000000000000000000000000000..5e07022277233e69cbecd17ee711b194157619ad --- /dev/null +++ b/src/views/MemberListView.vue @@ -0,0 +1,83 @@ +<template> + <div class="flex items-center justify-between mx-4"> + <div class="flex-1 min-w-0"> + <h2 + class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate" + > + {{ groupe.name }} + </h2> + <div + class="mt-1 flex flex-col sm:flex-row sm:flex-wrap sm:mt-0 sm:space-x-6" + > + <div class="mt-2 flex items-center text-sm text-gray-500"> + <svg + class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400" + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 20 20" + fill="currentColor" + aria-hidden="true" + > + <path + fill-rule="evenodd" + d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" + clip-rule="evenodd" + /> + </svg> + {{ groupe.address }} + </div> + </div> + </div> + <div class="flex"> + <span class="hidden sm:block"> + <button + v-if="adminStatus" + @click="edit()" + type="button" + class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" + > + <!-- Heroicon name: solid/pencil --> + <svg + class="-ml-1 mr-2 h-5 w-5 text-gray-500" + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 20 20" + fill="currentColor" + aria-hidden="true" + > + <path + d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" + /> + </svg> + Edit + </button> + </span> + </div> + </div> + <div class="h-screen bg-gray-200 content-top grid place-items-top"> + <member-list :admin="editing" /> + </div> +</template> + +<script> +import MemberList from "@/components/MemberList.vue"; + +export default { + data() { + return { + groupe: { + name: "Solsikken borettslag", + address: "Sollia 6, 7033 Trondheim", + }, + adminStatus: false, + editing: false, + }; + }, + components: { + MemberList, + }, + methods: { + edit() { + this.editing = !this.editing; + }, + }, +}; +</script> diff --git a/src/views/MessagesView.vue b/src/views/MessagesView.vue index fa142ea393224af5cb333962dbe5409a7369efa1..26fb14982553331defb80ce2c781d48d9a5e12aa 100644 --- a/src/views/MessagesView.vue +++ b/src/views/MessagesView.vue @@ -1,6 +1,6 @@ <template> <div> - <MessagesForm/> + <MessagesForm /> </div> </template> @@ -10,11 +10,9 @@ import MessagesForm from "@/components/MessagesForm"; export default { name: "MessagesView.vue", components: { - MessagesForm + MessagesForm, }, }; </script> -<style scoped> - -</style> \ No newline at end of file +<style scoped></style> diff --git a/src/views/NavBarView.vue b/src/views/NavBarView.vue index 87cd3356817b60ec39f69198607c4ed0401ba040..9e918114a32bfdd4e090cbecb59b5d32b00d15a8 100644 --- a/src/views/NavBarView.vue +++ b/src/views/NavBarView.vue @@ -1,19 +1,17 @@ <template> -<div> - <Navbar/> -</div> + <div> + <Navbar /> + </div> </template> <script> import Navbar from "@/components/NavBar"; export default { name: "NavBarView", - components:{ + components: { Navbar, }, -} +}; </script> -<style scoped> - -</style> \ No newline at end of file +<style scoped></style> diff --git a/src/views/NotificationView.vue b/src/views/NotificationView.vue index 110413201cc8b65b19a1a2e3dd252ce93f0aa2de..f30c038c323a055f83c6c7d38abe59a4494f2fa5 100644 --- a/src/views/NotificationView.vue +++ b/src/views/NotificationView.vue @@ -1,6 +1,6 @@ <template> <div> - <NotificationsForm/> + <NotificationsForm /> </div> </template> @@ -10,11 +10,9 @@ import NotificationsForm from "@/components/NotificationsForm"; export default { name: "NotificationView.vue", components: { - NotificationsForm + NotificationsForm, }, }; </script> -<style scoped> - -</style> \ No newline at end of file +<style scoped></style> diff --git a/src/views/ProfileView.vue b/src/views/ProfileView.vue index cfd2cefd902017ad7b867b7cfe447cce5648cf07..c4ea15c9d2d5c8f640b8180c226a64e4555535a2 100644 --- a/src/views/ProfileView.vue +++ b/src/views/ProfileView.vue @@ -1,6 +1,7 @@ -<!-- View for looking at different profile display methods --> <template> - <large-profile-card :isCurrentUser="true" /> + <div class="h-screen bg-gray-200 grid place-items-center"> + <large-profile-card :isCurrentUser="true" class="align-top" /> + </div> </template> <script> diff --git a/src/views/ResetPasswordView.vue b/src/views/ResetPasswordView.vue new file mode 100644 index 0000000000000000000000000000000000000000..eb2cd8d98a8ffa99dc1c546e02f2198f80e65e49 --- /dev/null +++ b/src/views/ResetPasswordView.vue @@ -0,0 +1,23 @@ +<template> + <div class="resetPassword"> + <ResetPassword></ResetPassword> + </div> +</template> + +<script> +import ResetPassword from "@/components/ResetPassword"; +export default { + name: "ResetPasswordView.vue", + components: { + ResetPassword, + }, +}; +</script> + +<style scoped> +.resetPassword { + background-color: white; + height: 100%; + overflow: auto; +} +</style> diff --git a/tests/unit/apiutil-login-mock.spec.js b/tests/unit/apiutil-login-mock.spec.js index b6d573beb45aff0450d4d52334a8e69cce950128..d7c12c918a32c867cc97a87dabea1e4d5eee4aca 100644 --- a/tests/unit/apiutil-login-mock.spec.js +++ b/tests/unit/apiutil-login-mock.spec.js @@ -4,14 +4,13 @@ import axios from "axios"; jest.mock("axios"); describe("testing mocking of apiutil.js", () => { - it("check that login fails with wrong credentials - against mock", async () => { - const loginRequest = { email: "wrong@email.com", - password: "thisiswrong123"}; + password: "thisiswrong123", + }; - const expectedLoginResponse = { isLoggedIn: false, token: "" } + const expectedLoginResponse = { isLoggedIn: false, token: "" }; axios.post.mockImplementation(() => Promise.resolve({ data: expectedLoginResponse }) @@ -19,24 +18,32 @@ describe("testing mocking of apiutil.js", () => { const loginResponse = await doLogin(loginRequest); - expect(loginResponse.token.isLoggedIn).toEqual(expectedLoginResponse.isLoggedIn); + expect(loginResponse.token.isLoggedIn).toEqual( + expectedLoginResponse.isLoggedIn + ); }); it("check that login succeeds when correct credentials - against mock", async () => { - const loginRequest = { email: "correct@email.com", - password: "thisiscorrect123"}; + password: "thisiscorrect123", + }; - const apiResponse = {isLoggedIn: true, token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM" + - "0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}; + const apiResponse = { + isLoggedIn: true, + token: + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM" + + "0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", + }; - const expectedLoginResponse = {isLoggedIn: false, token: ""}; + const expectedLoginResponse = { isLoggedIn: false, token: "" }; axios.post.mockImplementation(() => Promise.resolve({ data: apiResponse })); const loginResponse = await doLogin(loginRequest); - expect(loginResponse.token.isLoggedIn).not.toEqual(expectedLoginResponse.isLoggedIn); + expect(loginResponse.token.isLoggedIn).not.toEqual( + expectedLoginResponse.isLoggedIn + ); }); }); diff --git a/tests/unit/create-new-group.spec.js b/tests/unit/create-new-group.spec.js index 2b269b082ece04c8d1cbfa9c8eb9233d0d4e00f8..dfdceefa87bd978dab619a4c0a80fbb737789825 100644 --- a/tests/unit/create-new-group.spec.js +++ b/tests/unit/create-new-group.spec.js @@ -2,48 +2,43 @@ import { shallowMount } from "@vue/test-utils"; import CreateNewGroup from "@/components/CreateNewGroup.vue"; describe("CreateNewGroup elements rendering", () => { - - it("renders all labels", () => { - - const wrapper = shallowMount(CreateNewGroup); - - expect(wrapper.find('#radioBoxLabel').text()).toMatch("Synlighet"); - expect(wrapper.find('#radioBoxOpenLabel').text()).toMatch("Åpen"); - expect(wrapper.find('#radioBoxPrivateLabel').text()).toMatch("Privat"); - expect(wrapper.find('#titleLabel').text()).toMatch("Gruppenavn"); - expect(wrapper.find('#selectCategoryLabel').text()).toMatch("Kategori"); - expect(wrapper.find('#descriptionLabel').text()).toMatch("Beskrivelse"); - expect(wrapper.find('#imageLabel').text()).toMatch("Bilde"); - - }); - - it("Tests setting values of input field", async() => { - - const wrapper = shallowMount(CreateNewGroup); - - const titleInput = wrapper.find('#title'); - await titleInput.setValue("Fjellgata"); - expect(titleInput.element.value).toBe("Fjellgata"); - - const selectedCategory = wrapper.find('#categories'); - await selectedCategory.setValue("Borettslag"); - expect(selectedCategory.element.value).toBe("Borettslag"); - - const descriptionInput = wrapper.find('#description'); - await descriptionInput.setValue("Dette er et borettslag"); - expect(descriptionInput.element.value).toBe("Dette er et borettslag"); - }); - - it("Tests if radio box checks", async() => { - - const wrapper = shallowMount(CreateNewGroup); - - const radioInputOpen = wrapper.find('#flexRadioOpen'); - await radioInputOpen.setChecked(); - expect(radioInputOpen.element.checked).toBeTruthy(); - - const radioInputPrivate = wrapper.find('#flexRadioPrivate'); - await radioInputPrivate.setChecked(); - expect(radioInputPrivate.element.checked).toBeTruthy(); - }); + it("renders all labels", () => { + const wrapper = shallowMount(CreateNewGroup); + + expect(wrapper.find("#radioBoxLabel").text()).toMatch("Synlighet"); + expect(wrapper.find("#radioBoxOpenLabel").text()).toMatch("Åpen"); + expect(wrapper.find("#radioBoxPrivateLabel").text()).toMatch("Privat"); + expect(wrapper.find("#titleLabel").text()).toMatch("Gruppenavn"); + expect(wrapper.find("#selectCategoryLabel").text()).toMatch("Kategori"); + expect(wrapper.find("#descriptionLabel").text()).toMatch("Beskrivelse"); + expect(wrapper.find("#imageLabel").text()).toMatch("Bilde"); + }); + + it("Tests setting values of input field", async () => { + const wrapper = shallowMount(CreateNewGroup); + + const titleInput = wrapper.find("#title"); + await titleInput.setValue("Fjellgata"); + expect(titleInput.element.value).toBe("Fjellgata"); + + const selectedCategory = wrapper.find("#categories"); + await selectedCategory.setValue("Borettslag"); + expect(selectedCategory.element.value).toBe("Borettslag"); + + const descriptionInput = wrapper.find("#description"); + await descriptionInput.setValue("Dette er et borettslag"); + expect(descriptionInput.element.value).toBe("Dette er et borettslag"); + }); + + it("Tests if radio box checks", async () => { + const wrapper = shallowMount(CreateNewGroup); + + const radioInputOpen = wrapper.find("#flexRadioOpen"); + await radioInputOpen.setChecked(); + expect(radioInputOpen.element.checked).toBeTruthy(); + + const radioInputPrivate = wrapper.find("#flexRadioPrivate"); + await radioInputPrivate.setChecked(); + expect(radioInputPrivate.element.checked).toBeTruthy(); + }); }); diff --git a/tests/unit/search-item-list.spec.js b/tests/unit/search-item-list.spec.js index 6a01bbbdbe83b35b070e3fc9bf8ac9ed061ab6af..b7d0fbaeefd6dc5a2d634193815c3f51de131642 100644 --- a/tests/unit/search-item-list.spec.js +++ b/tests/unit/search-item-list.spec.js @@ -2,14 +2,11 @@ import { shallowMount } from "@vue/test-utils"; import SearchItemListComponent from "@/components/SearchItemListComponent.vue"; describe("CreateNewGroup elements rendering", () => { + it("Tests setting values of input field", async () => { + const wrapper = shallowMount(SearchItemListComponent); - it("Tests setting values of input field", async() => { - - const wrapper = shallowMount(SearchItemListComponent); - - const searchInput = wrapper.find('#searchInput'); - await searchInput.setValue("Dyson"); - expect(searchInput.element.value).toBe("Dyson"); - - }); + const searchInput = wrapper.find("#searchInput"); + await searchInput.setValue("Dyson"); + expect(searchInput.element.value).toBe("Dyson"); + }); });