diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d18bea..a361986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,23 +14,8 @@ jobs: working-directory: webapp steps: - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 with: - node-version: 18 - - run: npm ci - - run: npm test --coverage --watchAll - - name: Analyze with SonarCloud - uses: sonarsource/sonarcloud-github-action@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - unit-test-restapi: - runs-on: ubuntu-latest - defaults: - run: - working-directory: restapi - steps: - - uses: actions/checkout@v3 + fetch-depth: 0 - uses: actions/setup-node@v3 with: node-version: 18 @@ -42,7 +27,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} e2e-tests: - needs: [unit-test-webapp, unit-test-restapi] + needs: [unit-test-webapp] runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/lomap_en2a.yml b/.github/workflows/lomap_en2a.yml index 4d7debb..250cbd1 100644 --- a/.github/workflows/lomap_en2a.yml +++ b/.github/workflows/lomap_en2a.yml @@ -22,25 +22,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - unit-test-restapi: - runs-on: ubuntu-latest - defaults: - run: - working-directory: restapi - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 18 - - run: npm ci - - run: npm test --coverage --watchAll - - name: Analyze with SonarCloud - uses: sonarsource/sonarcloud-github-action@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} e2e-tests: - needs: [unit-test-webapp, unit-test-restapi] + needs: [unit-test-webapp] runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -48,7 +31,6 @@ jobs: with: node-version: 18 - run: npm --prefix webapp install - - run: npm --prefix restapi install - run: npm --prefix webapp run build - run: npm --prefix webapp run test:e2e docker-push-webapp: @@ -68,20 +50,6 @@ jobs: registry: ghcr.io workdir: webapp buildargs: API_URI - docker-push-restapi: - name: Push restapi Docker Image to GitHub Packages - runs-on: ubuntu-latest - needs: [e2e-tests] - steps: - - uses: actions/checkout@v3 - - name: Publish to Registry - uses: elgohr/Publish-Docker-Github-Action@v5 - with: - name: arquisoft/lomap_en2a/restapi - username: ${{ github.actor }} - password: ${{ secrets.DOCKER_PUSH_TOKEN }} - registry: ghcr.io - workdir: restapi # deploy: # name: Deploy over SSH # runs-on: ubuntu-latest diff --git a/restapi/tests/api.test.ts b/restapi/tests/api.test.ts deleted file mode 100644 index 1c2a33f..0000000 --- a/restapi/tests/api.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import request, {Response} from 'supertest'; -import express, { Application } from 'express'; -import * as http from 'http'; -import bp from 'body-parser'; -import cors from 'cors'; -import api from '../solidUtils/solidApi'; - -let app:Application; -let server:http.Server; - -beforeAll(async () => { - app = express(); - const port: number = 5000; - const options: cors.CorsOptions = { - origin: ['http://localhost:3000'] - }; - app.use(cors(options)); - app.use(bp.json()); - app.use("/api", api) - - server = app.listen(port, ():void => { - console.log('Restapi server for testing listening on '+ port); - }).on("error",(error:Error)=>{ - console.error('Error occured: ' + error.message); - }); -}); - -afterAll(async () => { - server.close() //close the server -}) - -describe('user ', () => { - /** - * Test that we can list users without any error. - */ - it('can be listed',async () => { - const response:Response = await request(app).get("/api/users/list"); - expect(response.statusCode).toBe(200); - }); - - /** - * Tests that a user can be created through the productService without throwing any errors. - */ - it('can be created correctly', async () => { - let username:string = 'Pablo' - let email:string = 'gonzalezgpablo@uniovi.es' - const response:Response = await request(app).post('/api/users/add').send({name: username,email: email}).set('Accept', 'application/json') - expect(response.statusCode).toBe(200); - }); -}); \ No newline at end of file diff --git a/webapp/jest.config.ts b/webapp/jest.config.ts index 0153d2e..8b35335 100644 --- a/webapp/jest.config.ts +++ b/webapp/jest.config.ts @@ -2,4 +2,5 @@ export default { transform: { "^.+\\.tsx?$": "ts-jest" }, + testEnvironment: 'jsdom', } \ No newline at end of file diff --git a/webapp/loadtestexample/GetUsersList.scala b/webapp/loadtestexample/GetUsersList.scala deleted file mode 100644 index adb9053..0000000 --- a/webapp/loadtestexample/GetUsersList.scala +++ /dev/null @@ -1,79 +0,0 @@ - -import scala.concurrent.duration._ - -import io.gatling.core.Predef._ -import io.gatling.http.Predef._ -import io.gatling.jdbc.Predef._ - -class GetUsersList extends Simulation { - - private val httpProtocol = http - .baseUrl("http://localhost:3000") - .inferHtmlResources(AllowList(), DenyList()) - .acceptHeader("*/*") - .acceptEncodingHeader("gzip, deflate") - .acceptLanguageHeader("en-US,en;q=0.5") - .userAgentHeader("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0") - - private val headers_0 = Map( - "Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", - "Upgrade-Insecure-Requests" -> "1" - ) - - private val headers_1 = Map("Accept" -> "image/avif,image/webp,*/*") - - private val headers_2 = Map( - "If-None-Match" -> """W/"21-Da2z2ryWGAvtwohXYJERIWJgKbU"""", - "Origin" -> "http://localhost:3000" - ) - - private val headers_3 = Map( - "Access-Control-Request-Headers" -> "content-type", - "Access-Control-Request-Method" -> "POST", - "Origin" -> "http://localhost:3000" - ) - - private val headers_4 = Map( - "Content-Type" -> "application/json", - "Origin" -> "http://localhost:3000" - ) - - private val headers_5 = Map( - "If-None-Match" -> """W/"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w"""", - "Origin" -> "http://localhost:3000" - ) - - private val uri1 = "localhost" - - private val scn = scenario("GetUsersList") - .exec( - http("request_0") - .get("/") - .headers(headers_0) - .resources( - http("request_1") - .get("/static/media/logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg") - .headers(headers_1), - http("request_2") - .get("http://" + uri1 + ":5000/api/users/list") - .headers(headers_2) - ) - ) - .pause(3) - .exec( - http("request_3") - .options("http://" + uri1 + ":5000/api/users/add") - .headers(headers_3) - .resources( - http("request_4") - .post("http://" + uri1 + ":5000/api/users/add") - .headers(headers_4) - .body(RawFileBody("getuserslist/0004_request.txt")), - http("request_5") - .get("http://" + uri1 + ":5000/api/users/list") - .headers(headers_5) - ) - ) - - setUp(scn.inject(constantUsersPerSec(3).during(15))).protocols(httpProtocol) -} \ No newline at end of file diff --git a/webapp/loadtestexample/getuserslist/0004_request.txt b/webapp/loadtestexample/getuserslist/0004_request.txt deleted file mode 100644 index 5d9bd63..0000000 --- a/webapp/loadtestexample/getuserslist/0004_request.txt +++ /dev/null @@ -1 +0,0 @@ -{"name":"Pablo","email":"gonzalezgpablo@uniovi.es"} \ No newline at end of file diff --git a/webapp/package-lock.json b/webapp/package-lock.json index bc4793b..a07d1ff 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -32,6 +32,7 @@ "react-slick": "^0.29.0", "shortid": "^2.2.16", "solid-auth-client": "^2.5.6", + "text-encoding": "^0.7.0", "typescript": "^4.9.4", "uuidv4": "^6.2.13", "web-vitals": "^2.1.2" @@ -45,7 +46,7 @@ "jest-cucumber": "^3.0.1", "jest-puppeteer": "^6.0.3", "puppeteer": "^13.0.1", - "react-scripts": "5.0.0", + "react-scripts": "^5.0.1", "start-server-and-test": "^1.14.0", "ts-jest": "^29.0.4", "ts-node-dev": "^2.0.0" @@ -35321,9 +35322,9 @@ } }, "node_modules/react-scripts": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.0.tgz", - "integrity": "sha512-3i0L2CyIlROz7mxETEdfif6Sfhh9Lfpzi10CtcGs1emDQStmZfWjJbAIMtRD0opVUjQuFWqHZyRZ9PPzKCFxWg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", "dev": true, "dependencies": { "@babel/core": "^7.16.0", @@ -35342,7 +35343,7 @@ "dotenv": "^10.0.0", "dotenv-expand": "^5.1.0", "eslint": "^8.3.0", - "eslint-config-react-app": "^7.0.0", + "eslint-config-react-app": "^7.0.1", "eslint-webpack-plugin": "^3.1.1", "file-loader": "^6.2.0", "fs-extra": "^10.0.0", @@ -35359,7 +35360,7 @@ "postcss-preset-env": "^7.0.1", "prompts": "^2.4.2", "react-app-polyfill": "^3.0.0", - "react-dev-utils": "^12.0.0", + "react-dev-utils": "^12.0.1", "react-refresh": "^0.11.0", "resolve": "^1.20.0", "resolve-url-loader": "^4.0.0", @@ -39830,6 +39831,12 @@ "node": ">=8" } }, + "node_modules/text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", + "deprecated": "no longer maintained" + }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -69216,9 +69223,9 @@ } }, "react-scripts": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.0.tgz", - "integrity": "sha512-3i0L2CyIlROz7mxETEdfif6Sfhh9Lfpzi10CtcGs1emDQStmZfWjJbAIMtRD0opVUjQuFWqHZyRZ9PPzKCFxWg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", "dev": true, "requires": { "@babel/core": "^7.16.0", @@ -69237,7 +69244,7 @@ "dotenv": "^10.0.0", "dotenv-expand": "^5.1.0", "eslint": "^8.3.0", - "eslint-config-react-app": "^7.0.0", + "eslint-config-react-app": "^7.0.1", "eslint-webpack-plugin": "^3.1.1", "file-loader": "^6.2.0", "fs-extra": "^10.0.0", @@ -69255,7 +69262,7 @@ "postcss-preset-env": "^7.0.1", "prompts": "^2.4.2", "react-app-polyfill": "^3.0.0", - "react-dev-utils": "^12.0.0", + "react-dev-utils": "^12.0.1", "react-refresh": "^0.11.0", "resolve": "^1.20.0", "resolve-url-loader": "^4.0.0", @@ -72766,6 +72773,11 @@ "minimatch": "^3.0.4" } }, + "text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==" + }, "text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", diff --git a/webapp/package.json b/webapp/package.json index 6f73edd..a1a314f 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -26,6 +26,7 @@ "react-slick": "^0.29.0", "shortid": "^2.2.16", "solid-auth-client": "^2.5.6", + "text-encoding": "^0.7.0", "typescript": "^4.9.4", "uuidv4": "^6.2.13", "web-vitals": "^2.1.2" @@ -34,7 +35,7 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --coverage", - "test:e2e": "start-server-and-test 'npm --prefix ../restapi start' http://localhost:5000/api/users/list prod 3000 \"cd e2e && jest\"", + "test:e2e": "start-server-and-test prod 3000 \"cd e2e && jest\"", "eject": "react-scripts eject", "prod": "ts-node-dev ./server.ts" }, diff --git a/webapp/src/App.test.tsx b/webapp/src/App.test.tsx deleted file mode 100644 index d6cfaa2..0000000 --- a/webapp/src/App.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/Source code/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/webapp/src/components/AddLocationForm.tsx b/webapp/src/components/AddLocationForm.tsx index 7d8780b..a4e0147 100644 --- a/webapp/src/components/AddLocationForm.tsx +++ b/webapp/src/components/AddLocationForm.tsx @@ -206,9 +206,9 @@ function AddLocationFormComp(props : AddLocationProps) : JSX.Element { { - categories.map((kind) => { // as many possible categories as items in Category enum + categories.map((kind,i) => { // as many possible categories as items in Category enum return ( - handleCheckedCategory(e)} + handleCheckedCategory(e)} >{kind} ) }) diff --git a/webapp/src/components/Friends.tsx b/webapp/src/components/Friends.tsx index fdfb8dd..fce45b2 100644 --- a/webapp/src/components/Friends.tsx +++ b/webapp/src/components/Friends.tsx @@ -63,7 +63,7 @@ function Friends() : JSX.Element {
- + diff --git a/webapp/src/components/FriendsDetail.test.tsx b/webapp/src/components/FriendsDetail.test.tsx new file mode 100644 index 0000000..85e38ec --- /dev/null +++ b/webapp/src/components/FriendsDetail.test.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import { render } from "@testing-library/react"; +import FriendsDetail from "./FriendsDetail"; +import { Friend } from '../../../restapi/users/User'; + +test('check username renders correctly',async () => { + let user : Friend = {username:String("username"), webID:String("webID"), pfp:""} + const {getByText}= render() + expect(getByText(user.username as string)).toBeInTheDocument(); +}) diff --git a/webapp/src/components/List.test.tsx b/webapp/src/components/List.test.tsx new file mode 100644 index 0000000..16f3227 --- /dev/null +++ b/webapp/src/components/List.test.tsx @@ -0,0 +1,74 @@ +import React from 'react' +import { render } from "@testing-library/react"; +import ListOfLocations from "./ListOfLocations"; + +const testLocations = [ + { + "url": "https://www.nycgo.com/attractions/the-metropolitan-museum-of-art/", + "name": "The Metropolitan Museum of Art", + "coordinates": { + "lng": -73.9632, + "lat": 40.7794 + }, + "category":[], + "description": "One of the world's largest and finest art museums, located in New York City.", + "images": [ + "https://www.metmuseum.org/-/media/images/visit/met-fifth-ave/met-5thave-exterior2-1024x640.jpg", + "https://www.metmuseum.org/-/media/images/about-the-met/mission-history/history/european-paintings/gallery-paintings/19800116_picasso_lg.jpg" + ] + }, + { + "url": "https://www.nps.gov/grca/index.htm", + "name": "Grand Canyon National Park", + "category":[], + "coordinates": { + "lng": -112.1121, + "lat": 36.1069 + }, + "description": "One of the most visited national parks in the United States, known for its awe-inspiring views of the Grand Canyon.", + "images": [ + "https://www.nps.gov/grca/planyourvisit/images/Grand-Canyon-view-wilderness-river-sunset_1.jpg", + "https://www.nps.gov/grca/planyourvisit/images/Grand-Canyon-view-wilderness-river-sunset_2.jpg" + ] + }, + { + "url": "https://www.disneyland.com/", + "name": "Disneyland Park", + "category":[], + "coordinates": { + "lng": -117.9189, + "lat": 33.8121 + }, + "description": "One of the most iconic theme parks in the world, located in Anaheim, California.", + "images": [ + "https://cdn1.parksmedia.wdprapps.disney.com/resize/mwImage/1/1280/720/75/dam/disneyland/home/destination/dlr_Hero_destination_full_767x431.jpg?1594128734436", + "https://cdn1.parksmedia.wdprapps.disney.com/resize/mwImage/1/1280/720/75/dam/disneyland/home/destination/dlr_Hero_attractions_full_767x431.jpg?1594133181294" + ] + }, + { + "url": "https://www.nps.gov/yell/index.htm", + "name": "Yellowstone National Park", + "category":[], + "coordinates": { + "lng": -110.7002, + "lat": 44.4279 + }, + "description": "The first national park in the world, known for its geothermal features and wildlife.", + "images": [ + "https://www.nps.gov/common/uploads/structured_data/3C86EB6B-1DD8-B71B-0BE6E0A7A8E1CE22.jpg", + "https://www.nps.gov/common/uploads/structured_data/3C86EB6B-1DD8-B71B-0BE27D9B72829723.jpg" + ] + }]; + +test('check that the location list renders propertly',async () => { + const {getByText}= render({}}>) + testLocations.forEach(location => { + let name = location.name; + expect(getByText(name)).toBeInTheDocument(); + }); +}) + +test('check that with no location the loading squeletons appear',async () => { + const {getByTestId}= render({}}>) + expect(getByTestId('loadingView')).toBeInTheDocument(); +}) \ No newline at end of file diff --git a/webapp/src/components/ListOfLocations.tsx b/webapp/src/components/ListOfLocations.tsx index 8f44801..54c3aa9 100644 --- a/webapp/src/components/ListOfLocations.tsx +++ b/webapp/src/components/ListOfLocations.tsx @@ -3,6 +3,8 @@ import {Flex, Box} from "@chakra-ui/react"; import { SkeletonCircle, SkeletonText } from '@chakra-ui/react' import LocationCard from './LocationCard'; + + type ListProps = { places : Array; setSelectedView: (viewName: JSX.Element) => void //function to change the selected view on the left @@ -14,6 +16,7 @@ function ListOfLocations(props : ListProps) : JSX.Element { if(props.places.length === 0) return( { + const {getByText}= render({}} key={1}>) + expect(getByText(testLocation.name)).toBeInTheDocument(); +}) + +test('check description displays correctly',async () => { + const {getByText}= render({}} key={1}>) + const truncatedDescription = testLocation.description.split(' ').slice(0, 5).join(' '); // truncate to first 5 words + expect(getByText(new RegExp(`^${truncatedDescription}`))).toBeInTheDocument(); +}) + +test('check image displays correctly when image in location',async () => { + const {container}= render({}} key={1}>) + expect(container.querySelector("img[src='https://www.metmuseum.org/-/media/images/visit/met-fifth-ave/met-5thave-exterior2-1024x640.jpg']")).toBeInTheDocument(); +}) + +test('check image displays correctly when NO image in location',async () => { + let locationWithouImage = { + "url": "https://www.nycgo.com/attractions/the-metropolitan-museum-of-art/", + "name": "The Metropolitan Museum of Art", + "coordinates": { + "lng": -73.9632, + "lat": 40.7794 + }, + "category":[], + "description": "One of the world's largest and finest art museums, located in New York City.", + "images": [] + }; + const {container}= render({}} key={1}>) + //we expect it to have loaded the 'no image' image for the locations + //by checking if the src of the image contains the name of the no images image + expect(container.querySelector('img')?.getAttribute('src')).toMatch(/no-pictures-picture/); +}) + +test('check change view on click to show location info expanded',async () => { + let selected = <> + const {container}= render({selected = view}} key={1}>) + //we click on the container + container.querySelector('img')?.click() + + //we check selected view has changed + expect(selected).not.toEqual(<>) +}) \ No newline at end of file diff --git a/webapp/src/components/LocationInfo.test.tsx b/webapp/src/components/LocationInfo.test.tsx new file mode 100644 index 0000000..4b850b1 --- /dev/null +++ b/webapp/src/components/LocationInfo.test.tsx @@ -0,0 +1,137 @@ +import React from 'react' +import { act, render, screen, fireEvent } from "@testing-library/react"; +import LocationInfo from "./LocationInfo"; +import { Location} from "../../../restapi/locations/Location"; + +//TODO +/* + These tests miss the parts where the solidManagement calls are done. Click on add a review (gets name from user) and + the update of the ratings using interface (that also takes the logged in user to change the value) + + Once mocking is understood it could be easy to test them, by now it has 70.4% coverage which is okay +*/ + + +const testLocation : Location = +{ + name: "Location alone", + coordinates: { lng: 1.234, lat: 5.678 }, + description: "Short description alone", + category: [], + reviews: [{ + "webId": "abc123", + "username":"usr", + "date": new Date("2022-03-15T12:00:00Z"), + "title": "Amazing experience", + "content": "I recently visited this location and was blown away by the beautiful scenery and friendly staff. The location was easy to find and exceeded my expectations in every way. I highly recommend this spot to anyone looking for a peaceful and memorable experience." + }, + { + "webId": "def456", + "username":"usr", + "date": new Date("2022-03-15T12:00:00Z"), + "title": "Disappointing experience", + "content": "I was excited to visit this location based on the reviews, but unfortunately it didn't live up to my expectations. The scenery was nice, but the staff wasn't very friendly and the facilities were not well-maintained. I wouldn't recommend this spot." + }, + { + "webId": "ghi789", + "username":"usr", + "date": new Date("2022-05-01T10:00:00Z"), + "title": "Great location for hiking", + "content": "I had a fantastic time hiking at this location. The trails were well-marked and provided stunning views of the surrounding area. The staff was helpful and provided useful information about the trails. I highly recommend this spot for anyone looking for a challenging and rewarding hiking experience." + } + + ], + images: [ + "https://www.metmuseum.org/-/media/images/visit/met-fifth-ave/met-5thave-exterior2-1024x640.jpg", + "https://www.metmuseum.org/-/media/images/about-the-met/mission-history/history/european-paintings/gallery-paintings/19800116_picasso_lg.jpg" + ], + ratings: new Map([["webId1", 1], ["webId2", 2], ["webId2", 3], ["webId2", 4], ["webId2", 5]]) +}; + +test('check title shows in view', async () => { + const { getByText } = render() + await act(async () => { + expect(getByText(testLocation.name)).toBeInTheDocument(); + }) +}) + +test('check description shows in view', async () => { + const { getByText } = render() + await act(async () => { + expect(getByText(testLocation.description)).toBeInTheDocument(); + }) +}) + +test('check images shows in view', async () => { + const { container } = render() + await act(async () => { + expect(container.querySelectorAll("img").length).toBe(testLocation.images?.length); + }) +}) + +test('check reviews are displayed correctly', async () => { + const { getByText } = render() + await act(async () => { + testLocation.reviews?.forEach(review => { + expect(getByText(review.title)).toBeInTheDocument(); + }); + }) +}) + +// test('check delete button is working', async () => { +// let deleteFunc = jest.fn() +// const { getByTestId } = render() +// //we click the deletion button +// await act(async () => { +// getByTestId('deleteLocationButton').click(); +// }) +// //we expect deleteFunct to have been called +// expect(deleteFunc).toBeCalledTimes(1); +// }) + + + +test('check ratings are shown in view', async () => { + const { getByTestId } = render() + //we will check the number of reviews + await act(async () => { + //we will check the number of reviews + expect(getByTestId('nRatings').textContent).toBe( + testLocation.ratings?.size.toString() + ); + }) + //we check the average to be well computed + expect(getByTestId('avgRatings').textContent).toBe('3.00') +}) + +test('check review addition form is working', async () => { + const { getByTestId, getByText, getByLabelText } = render() + //we get the button to add a review + let reviewButton = getByTestId('buttonReview') + //we click the button + await act(async () => { + reviewButton.click() + }) + //expected to have shown view to add a review + expect(getByText('Leave a review')).toHaveStyle({ visibility: 'visible' }) + //we try filling the form + let inputTitle = getByTestId('inputTitle'); + let inputBody = getByTestId('inputBody'); + //submit review button should not be available + let submitReviewButton = getByTestId('submitReviewButton'); + expect(submitReviewButton).toBeDisabled(); + //we fill the form + await act(async () => { + fireEvent.change(inputTitle, { target: { value: 'Test' } }); + fireEvent.change(inputBody, { target: { value: 'test body' } }); + }); + //now button should NOT be disabled + expect(submitReviewButton).not.toBeDisabled(); + //we close the menu of adding a review + await act(async () => { + fireEvent.click(getByTestId('closeButtonReview')); + }); + //we expect the add review window to not be in the screen + expect(getByText('Leave a review')).not.toHaveStyle({ visibility: 'hidden' }) +}) + diff --git a/webapp/src/components/LocationInfo.tsx b/webapp/src/components/LocationInfo.tsx index 7894aa5..580188d 100644 --- a/webapp/src/components/LocationInfo.tsx +++ b/webapp/src/components/LocationInfo.tsx @@ -139,11 +139,11 @@ const RatingSection = ({location, setLocation, session})=>{ Average rating: - {Number.isNaN(average)? 0 : average.toFixed(2)} + {Number.isNaN(average)? 0 : average.toFixed(2)} Number of ratings: - {total} + {total} @@ -206,15 +206,16 @@ const ReviewSection = ( {location ,setLocation,session}) =>{ closeOnBlur={false} > - + - + Leave a review Title - settitle(e.target.value)} @@ -227,6 +228,7 @@ const ReviewSection = ( {location ,setLocation,session}) =>{ } Body