diff --git a/README.md b/README.md index fb1f6eb8b91e5edb9de574056e10fdd8856ebce7..d75ae0c4ca45ebdfd33b67d37211cb0f45aa10cb 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,50 @@ -# frontend +# BoCo - Frontend + + +<img src="public/favicon.ico" height="100" title="hover text"> + +## Table of contents +1. [Installation](#project-setup) +1. [Running the project](#running-the-project) +1. [Running tests](#running-tests) ## Project setup + +To run the frontend node.js is required. +- Installation links + - [node.js](https://nodejs.org/en/download/) + +Install required dependencies by running ``` npm install ``` -### Compiles and hot-reloads for development -``` -npm run serve -``` +The frontend cannot run by itself and requires a backend service. The URL to this backend service needs to be provided in the environmental variables. This can be done in these steps -### Compiles and minifies for production -``` -npm run build -``` +- Create a file with the name ``.env`` in the root folder +- If the backend service uses the default configuration insert this into the file + ``` + VUE_APP_BASEURL=http://localhost:3000/api/ + ``` -### Run your unit tests -``` -npm run test:unit -``` -### Lints and fixes files +## Running the project +- To compile and run with hot-reloads for development + ``` + npm run serve + ``` + +- To compile and minify project for prodoction + ``` + npm run build + ``` + +## Running tests +To run the tests run the command: ``` -npm run lint +npm run test:unit ``` +This will run all the tests and provide a coverage report. Due to a bug with jest and vue there are tests and files missing in the coverage report. This is due to jest skipping files with ``ES6`` import. ### Customize configuration See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/src/components/ChatComponents/RentalMessage.vue b/src/components/ChatComponents/RentalMessage.vue index ba86c9f14a778c7767390a9c5c54e4aa7dba7226..df2823fec366f458226cb8c7b5d0bfeb9e701260 100644 --- a/src/components/ChatComponents/RentalMessage.vue +++ b/src/components/ChatComponents/RentalMessage.vue @@ -1,6 +1,6 @@ <template> <div class="message-container"> - <div class="message"> + <div class="message bg-gray-100 ring-1 ring-gray-300"> <div class="info"> <div class="text"> <h2 class="header">Ny utleie forespørsel</h2> @@ -135,7 +135,6 @@ export default { display: block; flex-direction: column; width: 100%; - background: #d1d5db; border-radius: 10px; padding: 10px; max-width: 50%; diff --git a/src/components/CommunityComponents/CommunityList.vue b/src/components/CommunityComponents/CommunityList.vue index 8354bd25ce4cd34d3644522768e19a6298e89ad6..136e50e6b7e9e26fd999f4575e84124185dd0bf8 100644 --- a/src/components/CommunityComponents/CommunityList.vue +++ b/src/components/CommunityComponents/CommunityList.vue @@ -1,6 +1,9 @@ <template> <!-- A list conatining all the communities --> - <p v-if="!communities.length" class="flex place-content-center text-gray-400"> + <p + v-if="!communities.length" + class="flex place-content-center text-gray-400 mt-8" + > Ingen grupper </p> <ul v-else> diff --git a/src/components/CommunityComponents/CommunityListItem.vue b/src/components/CommunityComponents/CommunityListItem.vue index 8001e01a3aaba188a781c75428ecfa28a02bbd72..bdbc170a9eb0dd0de0fb8a6ce1a1c6737de88325 100644 --- a/src/components/CommunityComponents/CommunityListItem.vue +++ b/src/components/CommunityComponents/CommunityListItem.vue @@ -54,10 +54,7 @@ v-if="!community.picture" class="h-10 w-10 flex flex-col justify-center items-center ml-2 mr-2" > - <UserGroupIcon - alt="Felleskapets bilde" - class="h-10 w-10 text-primary-dark" - /> + <UserGroupIcon alt="Bilde" class="h-10 w-10 text-primary-dark" /> </div> <div v-else @@ -65,8 +62,8 @@ > <img :src="community.picture" - alt="Fellsekaps bilde" - class="rounded-md" + alt="Bilde" + class="rounded-md h-14 w-14 object-contain" /> </div> <div class="flex-1 pl-1 overflow-hidden"> diff --git a/src/components/ItemComponents/EditItemForm.vue b/src/components/ItemComponents/EditItemForm.vue index 0283428444580fbf70c6aa9fb6ee525cffbedbf9..17f46207594dc9088e0903d7b4771f4f5359d664 100644 --- a/src/components/ItemComponents/EditItemForm.vue +++ b/src/components/ItemComponents/EditItemForm.vue @@ -1,4 +1,5 @@ <template> + <!-- Form for editing an item --> <div class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4" > @@ -355,6 +356,10 @@ export default { return true; }, + /** + * Validation gets checked, and if it returns true + * the item and the images gets updated. + */ async saveClicked() { if (this.checkValidation()) { let itemInfo = { @@ -376,6 +381,12 @@ export default { } }, + /** + * Adds image when an image is selected from file explorer. + * Posts it to the db and gets the id of the image posted in return. + * Adds that id to an image URL and saves it in an array. + * That array containing image URLs gets posted to the db when save is clicked. + */ async addImage(event) { var that = this; let image = event.target.files[0]; @@ -390,6 +401,11 @@ export default { fileReader.readAsArrayBuffer(image); }, + /** + * Runs every time a chech box under 'grupper' is changed(checked/unchecked). + * Finds out if it was checked or unchecked and adds/removes the community from + * the array based on that. + */ onChangeCommunity(e) { this.updatedItem.selectedCommunityId = e.target.value; let alreadyInGroupList = false; @@ -417,11 +433,19 @@ export default { } }, + /** + * Updates the selected category when it gets changed changes. + */ onChangeCategory(e) { this.updatedItem.selectedCategory = e.target.value; this.updatedItem.selectedCategories = [e.target.value]; }, + /** + * pre-selects (check marks) the community/communities the item + * is posted in so the user can see where the item already is posted and + * then change the community/communities + */ isInSelectedCommunity(id) { for (let i in this.updatedItem.selectedCommunities) { if (this.updatedItem.selectedCommunities[i] == id) { @@ -430,6 +454,10 @@ export default { } return false; }, + + /** + * Removes image from item + */ async removeImage(image) { let newImages = []; for (let i in this.updatedItem.images) { @@ -441,6 +469,10 @@ export default { }, }, + /** + * Gets the item before the page gets mounted so the item info + * is filled in and ready to be displayed to user. + */ async beforeCreate() { let itemID = await this.$router.currentRoute.value.params.id; let item = await ListingService.getItem(itemID); diff --git a/src/components/ItemComponents/ItemCard.vue b/src/components/ItemComponents/ItemCard.vue index b8125f4f70bcdfd289c1c5437ee9a31764911793..154468723a48de6ecb13ded2a9e06ae6ccf16dce 100644 --- a/src/components/ItemComponents/ItemCard.vue +++ b/src/components/ItemComponents/ItemCard.vue @@ -1,11 +1,12 @@ <template> + <!-- Item card, displays title, address, price per day and a picture --> <div class="mt-5 px-5"> <div - class="w-full h-full rounded bg-gray-200 overflow-hidden display:inline-block correct-size" + class="w-full h-full rounded bg-gray-100 ring-1 ring-gray-200 overflow-hidden display:inline-block correct-size cursor-pointer" > <div class="relative h-0 pb-[66.7%]"> <img - class="w-full h-full absolute inset-0" + class="w-full h-full object-contain absolute" :src="item.img || require('../../assets/default-product.png')" alt="Item image" /> diff --git a/src/components/ItemComponents/NewItemForm.vue b/src/components/ItemComponents/NewItemForm.vue index 36c84f664967cbb685a593cf64b237d49f30e9af..c465454ce47d792b479751e67bad7d1645e02a6e 100644 --- a/src/components/ItemComponents/NewItemForm.vue +++ b/src/components/ItemComponents/NewItemForm.vue @@ -1,4 +1,5 @@ <template> + <!-- Form for adding a new item --> <div class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4" > @@ -58,7 +59,7 @@ </option> </select> - <!-- error message for select box --> + <!-- error message for select category --> <div class="text-error-medium" v-for="(error, index) of v$.item.select.$errors" @@ -70,7 +71,7 @@ </div> </div> - <!-- Grupper --> + <!-- Community --> <div class="mb-6"> <label class="block text-sm font-medium text-gray-900 dark:text-gray-400" >Grupper</label @@ -95,9 +96,9 @@ </ul> </div> <!-- Error message for community --> - <label class="text-error-medium text-sm block">{{ - groupErrorMessage - }}</label> + <label class="text-error-medium text-sm block"> + {{ groupErrorMessage }} + </label> </div> <!-- price --> @@ -105,7 +106,7 @@ <label class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" id="priceLabel" - >Pris</label + >Pris per dag</label > <input type="number" @@ -198,8 +199,10 @@ accept="image/png" /> + <!-- Opens file explorer --> <colored-button :text="'Velg bilde'" @click="$refs.file.click()" /> + <!-- Shows chosen images --> <div v-for="image in item.images" :key="image" class="m-2"> <form-image-display :image="image" @remove="removeImage(image)" /> </div> @@ -307,7 +310,6 @@ export default { selectedGroupId: -1, selectedGroups: [], }, - //Kategorier skal legges inn ved api/hente fra db, her må det endres etterhvert categories: [ "Antikviteter og kunst", "Dyr og utstyr", @@ -326,6 +328,12 @@ export default { }; }, methods: { + + /** + * Checks validation. Checks also if any community is selected. + * If no community is selected or any other field isn't valid + * false is returned, otherwise true is returned. + */ checkValidation: function () { this.v$.item.$touch(); if (this.v$.item.$invalid || this.item.selectedGroups.length === 0) { @@ -337,6 +345,11 @@ export default { return true; }, + /** + * When save is clicked, the validation gets checked. If validated, + * the user is parsed from the token to get the userId. Then the item + * and the pictures are posted to db. + */ async saveClicked() { if (this.checkValidation()) { this.checkUser(); @@ -358,11 +371,20 @@ export default { } }, + /** + * Parses user from token and uses it when posting item in saveClciked method + */ checkUser: async function () { let user = parseUserFromToken(this.$store.state.user.token); this.item.userId = parseInt(user.accountId); }, + /** + * Adds image when an image is selected from file explorer. + * Posts it to the db and gets the id of the image posted in return. + * Adds that id to an image URL and saves it in an array. + * That array containing image URLs gets posted to the db when save is clicked. + */ addImage: async function (event) { var that = this; let image = event.target.files[0]; @@ -377,6 +399,11 @@ export default { fileReader.readAsArrayBuffer(image); }, + /** + * Runs every time a chech box under 'grupper' is changed(checked/unchecked). + * Finds out if it was checked or unchecked and adds/removes the community from + * the array based on that. + */ onChangeGroup: function (e) { this.selectedGroupId = e.target.value; let alreadyInGroupList = false; @@ -397,6 +424,7 @@ export default { } }, + async removeImage(image) { let newImages = []; for (let i in this.item.images) { diff --git a/src/components/ItemComponents/SearchItemList.vue b/src/components/ItemComponents/SearchItemList.vue index 00ed0583f51be18a36e249fb9e04a599a840d862..7ba86f608346b526487791f2cdaf8c32733e2fec 100644 --- a/src/components/ItemComponents/SearchItemList.vue +++ b/src/components/ItemComponents/SearchItemList.vue @@ -1,4 +1,5 @@ <template> + <!-- A template for searching in item list --> <section class="relative w-full max-w-md px-5 py-4 mx-auto rounded-md"> <div class="relative" id="searchComponent"> <span class="absolute inset-y-0 left-0 flex items-center pl-3"> @@ -17,7 +18,7 @@ type="text" id="searchInput" class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" - placeholder="Search" + placeholder="Søk" v-model="search" /> </div> @@ -54,12 +55,6 @@ export default { }, }, - /** - * Her må det lages en metode som henter alle items (i en gruppe) fra databasen. - * De kan deretter bli pusha inn i items array, og da burde de bli displayet i lista. - * Når denne metoden er på plass kan items[] i data tømmes. Da vil alt dataen komme fra db. - */ - data() { return { items: [ diff --git a/src/components/RentingComponents/NewRent.vue b/src/components/RentingComponents/NewRent.vue index f0609f0ccaa7515c53d4839578ae77dca6bd510b..5b2647e4dbe76e592887f7464862293cc07792d3 100644 --- a/src/components/RentingComponents/NewRent.vue +++ b/src/components/RentingComponents/NewRent.vue @@ -42,6 +42,7 @@ </div> <div> <notification-modal + id="notification-modal" @click="routeToChat" :visible="confirmed" :title="'Vellykket'" diff --git a/src/components/UserAuthComponents/RegisterForm.vue b/src/components/UserAuthComponents/RegisterForm.vue index da8011bdce8f479730d0e8e16b082a09842243ba..d91f5bdfb3aa61ce6a2ea630c1bb24849c90fefd 100644 --- a/src/components/UserAuthComponents/RegisterForm.vue +++ b/src/components/UserAuthComponents/RegisterForm.vue @@ -25,14 +25,13 @@ v-for="(error, index) of v$.email.$errors" :key="index" > - <div - class="text-error-medium text-sm" - v-show="showError" - id="emailErrorId" - > + <div class="text-error-medium text-sm" v-show="showError"> {{ error.$message }} </div> </div> + <div class="text-error-medium text-sm" v-show="errorMessage"> + {{ errorMessage }} + </div> </div> <div> @@ -166,7 +165,7 @@ <script> import useVuelidate from "@vuelidate/core"; -import { doLogin, registerUser } from "@/utils/apiutil"; +import { doLogin } from "@/utils/apiutil"; import { required, email, @@ -246,10 +245,7 @@ export default { //If a user is created succsessfully, try to login //If we get this far, we will be pushed anyway so there is no point updating "loading" - if (!userCreated) { - this.errorMessage = "Could not create user."; - return; - } + if (!userCreated) return; const loginRequest = { email: this.email, @@ -270,17 +266,16 @@ export default { await this.$router.push("/"); }, async sendRegisterRequest() { - const registerInfo = { + const userInfo = { email: this.email, firstName: this.firstName, - lastname: this.lastName, + lastName: this.lastName, password: this.password, address: this.address, }; - - const response = await registerUser(registerInfo); - - return response.status === 200; + const res = await UserService.registerUser(userInfo); + this.errorMessage = res; + return res.status === 200; }, }, }; diff --git a/src/components/UserProfileComponents/UserItems.vue b/src/components/UserProfileComponents/UserItems.vue index 418a4f22fa9e684959fe6cfa2d5033c7ce5671c3..ac1736b5e713e14625729087f0493c4b859e55bf 100644 --- a/src/components/UserProfileComponents/UserItems.vue +++ b/src/components/UserProfileComponents/UserItems.vue @@ -3,7 +3,7 @@ Mine gjenstander </div> <!-- Search field --> - <div class="relative" id="searchComponent"> + <div class="relative mx-4" id="searchComponent"> <span class="absolute inset-y-0 left-0 flex items-center pl-3"> <svg class="w-5 h-5 text-gray-400" viewBox="0 0 24 24" fill="none"> <path @@ -20,12 +20,12 @@ type="text" id="searchInput" class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" - placeholder="Search" + placeholder="Søk" v-model="search" @change="searchWritten" /> </div> - <div class="absolute inset-x-0 px-5 py-3"> + <div class="absolute inset-x-0"> <!-- ItemCards --> <div class="flex items-center justify-center w-screen"> <!-- Shows items based on pagination --> @@ -39,18 +39,18 @@ v-for="item in visibleItems" :key="item" > - <ItemCard - id="ItemCardPage" - class="ItemCard w-fit h-fit" - :item="item" - /> - - <TripleDotButton class="DotButton" @click="openDotMenu(item)"> - </TripleDotButton> + <div class="w-full"> + <ItemCard + id="ItemCardPage" + class="ItemCard w-full h-full" + :item="item" + /> + </div> + <TripleDotButton class="DotButton" @click="openDotMenu(item)" /> <div v-show="item.toggle" - class="options z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700" + class="options z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700 pt-4 pl-12" > <ul class="py-1 absolute bg-white ring-1 ring-gray-300 rounded-xl" @@ -109,9 +109,14 @@ v-if="showSearchedItems" > <div class="cardContainer" v-for="item in searchedItems" :key="item"> - <ItemCard id="ItemCardSearch" class="ItemCard" :item="item" /> - <TripleDotButton class="DotButton" @click="openDotMenu(item)"> - </TripleDotButton> + <div class="w-full"> + <ItemCard + id="ItemCardSearch" + class="ItemCard w-full h-full" + :item="item" + /> + </div> + <TripleDotButton class="DotButton" @click="openDotMenu(item)" /> <div v-show="item.toggle" @@ -311,6 +316,7 @@ export default { .cardContainer { position: relative; } + .DotButton { position: absolute; right: 40px; diff --git a/src/services/user.service.js b/src/services/user.service.js index b6d908ba08d23bbfc32c6229ff1c093229c57a39..1639127d4706c607415316a00f95829f00e3eef5 100644 --- a/src/services/user.service.js +++ b/src/services/user.service.js @@ -124,5 +124,19 @@ class UserService { }) .catch((err) => console.log(err)); } + + async registerUser(userInfo) { + return await axios + .post(API_URL + "register", userInfo) + .then((res) => { + return res; + }) + .catch((err) => { + if (err.response) { + return err.response.data; + } + console.error(err); + }); + } } export default new UserService(); diff --git a/src/utils/apiutil.js b/src/utils/apiutil.js index 7b42b8219865c3b58a02716b8326923f1946e09d..74e9b481338da2f22eda07ebb48bdc0137b5c23c 100644 --- a/src/utils/apiutil.js +++ b/src/utils/apiutil.js @@ -18,21 +18,6 @@ export function doLogin(loginRequest) { }); } -export function registerUser(registerInfo) { - return axios - .post(API_URL + "register", { - email: registerInfo.email, - firstName: registerInfo.firstName, - lastName: registerInfo.lastname, - password: registerInfo.password, - address: registerInfo.address, - }) - .then((response) => { - return response; - }) - .catch((err) => console.error(err)); -} - export async function getUser(userid) { return axios .get(API_URL + "users/" + userid + "/profile", { diff --git a/src/views/CommunityViews/CommunityView.vue b/src/views/CommunityViews/CommunityView.vue index 329917065b0679060da6503891b05c932ebaf18a..11767faa7299f22ceb232eb8045c4441b096faa0 100644 --- a/src/views/CommunityViews/CommunityView.vue +++ b/src/views/CommunityViews/CommunityView.vue @@ -48,7 +48,7 @@ type="text" id="searchInput" class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" - placeholder="Search" + placeholder="Søk" v-model="search" @change="searchWritten" /> diff --git a/src/views/ItemViews/EditItemView.vue b/src/views/ItemViews/EditItemView.vue index 763ecdafeb6145a16e7518c4630cf1ebdb79e5d0..cdb4f27044b4c7e19c1431a7579edef43ba38871 100644 --- a/src/views/ItemViews/EditItemView.vue +++ b/src/views/ItemViews/EditItemView.vue @@ -1,6 +1,7 @@ <template> + <!-- A view for editing the item --> <div class="h-screen grid md:mt-8"> - <edit-item-form :initialItem="initialItem" :communities="communities" /> + <edit-item-form/> </div> </template> diff --git a/src/views/ItemViews/NewItemView.vue b/src/views/ItemViews/NewItemView.vue index fc9db3697ba1fe00f740bb7457f233be22e6cee5..a6213c5e7c284b2980f49a5d53e6b135ed614c34 100644 --- a/src/views/ItemViews/NewItemView.vue +++ b/src/views/ItemViews/NewItemView.vue @@ -14,5 +14,3 @@ export default { }, }; </script> - -<style scoped></style> diff --git a/src/views/ItemViews/SearchItemListView.vue b/src/views/ItemViews/SearchItemListView.vue index 7da50f9397c5dee29f471267b8cb08866edcccfb..816e04e2b43a0673bb142277e79e73cc5685347d 100644 --- a/src/views/ItemViews/SearchItemListView.vue +++ b/src/views/ItemViews/SearchItemListView.vue @@ -1,4 +1,5 @@ <template> + <!-- View for search item component --> <SearchItemListComponent></SearchItemListComponent> </template> @@ -11,5 +12,3 @@ export default { }, }; </script> - -<style scoped></style> diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/community-list-item.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list-item.spec.js.snap index 4edde89c2c743d9c2411aa4a1a5c1403b7077c70..d52b806eba9a5cd9dcc8828d4bb79948c834e6ee 100644 --- a/tests/unit/component-tests/community-component-tests/__snapshots__/community-list-item.spec.js.snap +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list-item.spec.js.snap @@ -13,8 +13,8 @@ exports[`CommunityListItem component renders correctly 1`] = ` class="h-3 w-14 flex flex-col justify-center items-center ml-2 mt-4 mb-4 mr-2" > <img - alt="Fellsekaps bilde" - class="rounded-md" + alt="Bilde" + class="rounded-md h-14 w-14 object-contain" src="string" /> </div> diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/community-list.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list.spec.js.snap index fc8d4f6d97bfaa6bc5e459e517c0a2cd8b490e1e..c1b47cc4abaff7cddcd9ae8b01245615c9e5b528 100644 --- a/tests/unit/component-tests/community-component-tests/__snapshots__/community-list.spec.js.snap +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list.spec.js.snap @@ -23,8 +23,8 @@ exports[`CommunityList component renders correctly 1`] = ` class="h-3 w-14 flex flex-col justify-center items-center ml-2 mt-4 mb-4 mr-2" > <img - alt="Fellsekaps bilde" - class="rounded-md" + alt="Bilde" + class="rounded-md h-14 w-14 object-contain" src="string" /> </div> @@ -74,8 +74,8 @@ exports[`CommunityList component renders correctly 1`] = ` class="h-3 w-14 flex flex-col justify-center items-center ml-2 mt-4 mb-4 mr-2" > <img - alt="Fellsekaps bilde" - class="rounded-md" + alt="Bilde" + class="rounded-md h-14 w-14 object-contain" src="string" /> </div> diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/item-card.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/item-card.spec.js.snap index 9167369f515802cca42dd7be7026189a2fa8c4be..d77de4b0af5129621991ac5931424977ad9af958 100644 --- a/tests/unit/component-tests/community-component-tests/__snapshots__/item-card.spec.js.snap +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/item-card.spec.js.snap @@ -2,42 +2,49 @@ exports[`ItemCard component renders correctly 1`] = ` <div - class="mt-5 px-5" + data-v-app="" > + + <!-- Item card, displays title, address, price per day and a picture --> <div - class="w-full h-full rounded bg-gray-200 overflow-hidden display:inline-block correct-size" + class="mt-5 px-5" > <div - class="relative h-0 pb-[66.7%]" + class="w-full h-full rounded bg-gray-100 ring-1 ring-gray-200 overflow-hidden display:inline-block correct-size cursor-pointer" > - <img - alt="Item image" - class="w-full h-full absolute inset-0" - src="String" - /> - </div> - <div - class="p-1 m-1 bottom-0" - > - <p - class="font-bold text-sm" - id="title" - > - String - </p> - <p - class="text-gray-700 text-xs" - id="price" + <div + class="relative h-0 pb-[66.7%]" > - 0 kr - </p> - <p - class="text-gray-700 text-xs font-bold" - id="adress" + <img + alt="Item image" + class="w-full h-full object-contain absolute" + src="String" + /> + </div> + <div + class="p-1 m-1 bottom-0" > - String - </p> + <p + class="font-bold text-sm" + id="title" + > + String + </p> + <p + class="text-gray-700 text-xs" + id="price" + > + 0 kr + </p> + <p + class="text-gray-700 text-xs font-bold" + id="adress" + > + String + </p> + </div> </div> </div> + </div> `; diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/new-item-form.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/new-item-form.spec.js.snap index d302a72c8efaf512cedea636c34b06d59abc050e..1788f9305c5a342b282e03657a5b7351548a3c4c 100644 --- a/tests/unit/component-tests/community-component-tests/__snapshots__/new-item-form.spec.js.snap +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/new-item-form.spec.js.snap @@ -2,235 +2,244 @@ exports[`NewItemForm component renders correctly 1`] = ` <div - class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4" + data-v-app="" > - <!-- Component heading --> - <h3 - class="text-xl font-medium text-center text-primary-light mt-4 mb-8" - > - Opprett ny utleie - </h3> - <!-- Title --> - <div - class="mb-6" - > - <label - class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" - id="titleLabel" - > - Tittel - </label> - <input - class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" - id="title" - required="" - type="text" - /> - <!-- error message for title--> - - - </div> - <!-- Select category --> + + <!-- Form for adding a new item --> <div - class="mb-6" + class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4" > - <label - class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" - id="selectCategoryLabel" + <!-- Component heading --> + <h3 + class="text-xl font-medium text-center text-primary-light mt-4 mb-8" > - Kategori - </label> - <select - class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" - id="categories" + Opprett ny utleie + </h3> + <!-- Title --> + <div + class="mb-6" > - <option - class="text-gray-400" - disabled="" - value="" + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + id="titleLabel" > - Velg en kategori - </option> + Tittel + </label> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="title" + required="" + type="text" + /> + <!-- error message for title--> - <option - class="text-gray-900 text-sm" - > - Antikviteter og kunst - </option> - <option - class="text-gray-900 text-sm" - > - Dyr og utstyr - </option> - <option - class="text-gray-900 text-sm" + + </div> + <!-- Select category --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + id="selectCategoryLabel" > - Elektronikk og hvitevarer - </option> - <option - class="text-gray-900 text-sm" + Kategori + </label> + <select + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="categories" > - Foreldre og barn - </option> - <option - class="text-gray-900 text-sm" + <option + class="text-gray-400" + disabled="" + value="" + > + Velg en kategori + </option> + + <option + class="text-gray-900 text-sm" + > + Antikviteter og kunst + </option> + <option + class="text-gray-900 text-sm" + > + Dyr og utstyr + </option> + <option + class="text-gray-900 text-sm" + > + Elektronikk og hvitevarer + </option> + <option + class="text-gray-900 text-sm" + > + Foreldre og barn + </option> + <option + class="text-gray-900 text-sm" + > + Fritid, hobby og underholdning + </option> + <option + class="text-gray-900 text-sm" + > + Hage, oppussing og hus + </option> + <option + class="text-gray-900 text-sm" + > + Klær, kosmetikk og tilbehør + </option> + <option + class="text-gray-900 text-sm" + > + Møbler og interiør + </option> + <option + class="text-gray-900 text-sm" + > + Næringsvirksomhet + </option> + <option + class="text-gray-900 text-sm" + > + Sport og friluftsliv + </option> + <option + class="text-gray-900 text-sm" + > + Utstyr til bil, båt og MC + </option> + + </select> + <!-- error message for select category --> + + + </div> + <!-- Community --> + <div + class="mb-6" + > + <label + class="block text-sm font-medium text-gray-900 dark:text-gray-400" > - Fritid, hobby og underholdning - </option> - <option - class="text-gray-900 text-sm" + Grupper + </label> + <div + class="overflow-auto w-full max-h-32 mt-2 text-base list-none bg-white rounded divide-y divide-gray-100 dark:bg-gray-700" > - Hage, oppussing og hus - </option> - <option - class="text-gray-900 text-sm" + <ul + aria-labelledby="dropdownDefault" + class="py-1" + > + <li> + + + </li> + </ul> + </div> + <!-- Error message for community --> + <label + class="text-error-medium text-sm block" + /> + </div> + <!-- price --> + <div + class="mb-6 mt-4" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + id="priceLabel" > - Klær, kosmetikk og tilbehør - </option> - <option - class="text-gray-900 text-sm" + Pris per dag + </label> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="price" + required="" + type="number" + /> + <!-- error message for price --> + + + </div> + <!-- Description --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + id="descriptionLabel" > - Møbler og interiør - </option> - <option - class="text-gray-900 text-sm" + Beskrivelse + </label> + <textarea + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="description" + required="" + rows="4" + /> + <!-- error message for description --> + + + </div> + <!-- Address --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + id="addressLabel" > - Næringsvirksomhet - </option> - <option - class="text-gray-900 text-sm" + Adresse + </label> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="adress" + required="" + type="text" + /> + <!-- error message for address--> + + + </div> + <!-- Images --> + <div> + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + id="imageLabel" > - Sport og friluftsliv - </option> - <option - class="text-gray-900 text-sm" + Bilder (bildene må være .png) + </label> + <input + accept="image/png" + style="display: none;" + type="file" + /> + <!-- Opens file explorer --> + <button + class="flex items-center px-2 py-2 font-medium tracking-wide capitalize text-white transition-colors duration-200 transform rounded-md focus:outline-none focus:ring focus:ring-opacity-80 min-w-{20px} bg-primary-medium hover:bg-primary-dark focus:ring-primary-light" > - Utstyr til bil, båt og MC - </option> + Velg bilde + </button> + <!-- Shows chosen images --> - </select> - <!-- error message for select box --> - - - </div> - <!-- Grupper --> - <div - class="mb-6" - > - <label - class="block text-sm font-medium text-gray-900 dark:text-gray-400" - > - Grupper - </label> + + </div> + <!-- Save item button --> <div - class="overflow-auto w-full max-h-32 mt-2 text-base list-none bg-white rounded divide-y divide-gray-100 dark:bg-gray-700" + class="float-right" > - <ul - aria-labelledby="dropdownDefault" - class="py-1" + <button + class="flex items-center px-2 py-2 font-medium tracking-wide capitalize text-white transition-colors duration-200 transform rounded-md focus:outline-none focus:ring focus:ring-opacity-80 min-w-{20px} bg-primary-medium hover:bg-primary-dark focus:ring-primary-light" + id="saveButton" > - <li> - - - </li> - </ul> + Lagre + </button> </div> - <!-- Error message for community --> - <label - class="text-error-medium text-sm block" - /> - </div> - <!-- price --> - <div - class="mb-6 mt-4" - > - <label - class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" - id="priceLabel" - > - Pris - </label> - <input - class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" - id="price" - required="" - type="number" - /> - <!-- error message for price --> - - - </div> - <!-- Description --> - <div - class="mb-6" - > - <label - class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" - id="descriptionLabel" - > - Beskrivelse - </label> - <textarea - class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" - id="description" - required="" - rows="4" - /> - <!-- error message for description --> - - - </div> - <!-- Address --> - <div - class="mb-6" - > - <label - class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" - id="addressLabel" - > - Adresse - </label> - <input - class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" - id="adress" - required="" - type="text" - /> - <!-- error message for address--> - - - </div> - <!-- Images --> - <div> - <label - class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" - id="imageLabel" - > - Bilder (bildene må være .png) - </label> - <input - accept="image/png" - style="display: none;" - type="file" - /> - <button - class="flex items-center px-2 py-2 font-medium tracking-wide capitalize text-white transition-colors duration-200 transform rounded-md focus:outline-none focus:ring focus:ring-opacity-80 min-w-{20px} bg-primary-medium hover:bg-primary-dark focus:ring-primary-light" - > - Velg bilde - </button> - - - </div> - <!-- Save item button --> - <div - class="float-right" - > - <button - class="flex items-center px-2 py-2 font-medium tracking-wide capitalize text-white transition-colors duration-200 transform rounded-md focus:outline-none focus:ring focus:ring-opacity-80 min-w-{20px} bg-primary-medium hover:bg-primary-dark focus:ring-primary-light" - id="saveButton" - > - Lagre - </button> </div> + </div> `; diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/search-item-list.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/search-item-list.spec.js.snap index 59eecbb9003356b0debaa8228f3785d489e3ec98..9ccc19c0abc78e6bb844dc550974c7bb02cecb3d 100644 --- a/tests/unit/component-tests/community-component-tests/__snapshots__/search-item-list.spec.js.snap +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/search-item-list.spec.js.snap @@ -1,55 +1,62 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`SearchItemListComponent elements rendering renders correctly 1`] = ` -<section - class="relative w-full max-w-md px-5 py-4 mx-auto rounded-md" +<div + data-v-app="" > - <div - class="relative" - id="searchComponent" + + <!-- A template for searching in item list --> + <section + class="relative w-full max-w-md px-5 py-4 mx-auto rounded-md" > - <span - class="absolute inset-y-0 left-0 flex items-center pl-3" + <div + class="relative" + id="searchComponent" > - <svg - class="w-5 h-5 text-gray-400" - fill="none" - viewBox="0 0 24 24" + <span + class="absolute inset-y-0 left-0 flex items-center pl-3" > - <path - d="M21 21L15 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" - stroke="currentColor" - stroke-linecap="round" - stroke-linejoin="round" - stroke-width="2" - /> - </svg> - </span> - <input - class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" - id="searchInput" - placeholder="Search" - type="text" - /> - </div> - <div - class="absolute inset-x-0 px-6 py-3 mt-4 border-2 border-slate-500" - > + <svg + class="w-5 h-5 text-gray-400" + fill="none" + viewBox="0 0 24 24" + > + <path + d="M21 21L15 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" + stroke="currentColor" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="2" + /> + </svg> + </span> + <input + class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" + id="searchInput" + placeholder="Søk" + type="text" + /> + </div> <div - class="grid grid-cols-2" + class="absolute inset-x-0 px-6 py-3 mt-4 border-2 border-slate-500" > - - <item-card-stub - item="[object Object]" - /> - <item-card-stub - item="[object Object]" - /> - <item-card-stub - item="[object Object]" - /> - + <div + class="grid grid-cols-2" + > + + <item-card-stub + item="[object Object]" + /> + <item-card-stub + item="[object Object]" + /> + <item-card-stub + item="[object Object]" + /> + + </div> </div> - </div> -</section> + </section> + +</div> `; diff --git a/tests/unit/component-tests/renting-compnents-tests/new-rent.spec.js b/tests/unit/component-tests/renting-compnents-tests/new-rent.spec.js index 3f8ffafa68bf5dd606afdeda9214b57871ff174f..c4cb88e85e7a68134b52dba817ebd7375e29888b 100644 --- a/tests/unit/component-tests/renting-compnents-tests/new-rent.spec.js +++ b/tests/unit/component-tests/renting-compnents-tests/new-rent.spec.js @@ -1,16 +1,16 @@ import { mount } from "@vue/test-utils"; import NewRent from "@/components/RentingComponents/NewRent.vue"; +import axios from "axios"; + +jest.mock("axios"); +let mockRouter; describe("Confirm and send a rent request", () => { + mockRouter = { + go: jest.fn() + } + let wrapper; - const route = { - params: { - id: 1, - }, - }; - const router = { - push: jest.fn(), - }; beforeEach(() => { wrapper = mount(NewRent, { props: { @@ -24,12 +24,11 @@ describe("Confirm and send a rent request", () => { isAccepted: false, }, }, - global: { - mocks: { - $route: route, - $router: router, - }, - }, + global:{ + mocks:{ + $router: mockRouter + } + } }); }); @@ -37,10 +36,26 @@ describe("Confirm and send a rent request", () => { expect(wrapper.exists()).toBeTruthy(); }); - it("Check if fields show correct informations", () => { + it("Check that fields show correct informations", () => { expect(wrapper.find("#rentTitle").text()).toEqual("Telt"); expect(wrapper.find("#fromTime").text()).toMatch("19. September 2022"); expect(wrapper.find("#toTime").text()).toMatch("23. September 2022"); expect(wrapper.find("#price").text()).toEqual("Totaltpris: 200 kr"); }); + + it("Check that clicking rent sends post request", async () => { + const button = wrapper.find("#confirmButton"); + axios.post.mockResolvedValueOnce(); + button.trigger("click"); + await wrapper.vm.$nextTick(); + expect(axios.post).toHaveBeenCalledTimes(1); + }); + + it("Checks that page is reloaded when cancelButton is press", async () =>{ + const button = wrapper.find("#cancelButton"); + button.trigger("click"); + await wrapper.vm.$nextTick(); + expect(mockRouter.go).toHaveBeenCalledTimes(1); + expect(mockRouter.go).toHaveBeenCalledWith(0); + }) }); diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap index 193cbfa3c50d17fb2f50c439c23fe6b0031c3d33..4528659ba8dc6ec84a04c67327896759074d5ae7 100644 --- a/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap @@ -24,6 +24,10 @@ exports[`RegisterFormComponent renders correctly 1`] = ` <!-- error message --> + <div + class="text-error-medium text-sm" + style="display: none;" + /> </div> <div> <input diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/user-items.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/user-items.spec.js.snap index db5d7bf26553750dd6c9f3789f9541ffc2d2f071..a5812dd15944a413f9281e682a1b364681eb63c9 100644 --- a/tests/unit/component-tests/user-component-tests/__snapshots__/user-items.spec.js.snap +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/user-items.spec.js.snap @@ -13,7 +13,7 @@ exports[`UserItems component renders correctly 1`] = ` </div> <!-- Search field --> <div - class="relative" + class="relative mx-4" id="searchComponent" > <span @@ -36,12 +36,12 @@ exports[`UserItems component renders correctly 1`] = ` <input class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" id="searchInput" - placeholder="Search" + placeholder="Søk" type="text" /> </div> <div - class="absolute inset-x-0 px-5 py-3" + class="absolute inset-x-0" > <!-- ItemCards --> <div