README.md 8.04 KB
Newer Older
Andreas Wilson's avatar
readme    
Andreas Wilson committed
1
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.idi.ntnu.no/#https://gitlab.stud.idi.ntnu.no/it2810-h20/team-32/project-3-it2810-group-32)
Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
2

Peder Espen's avatar
Peder Espen committed
3
4
# Project 3 - IT2810 Group 32

5
# How to run locally
Eskild Brobak's avatar
Eskild Brobak committed
6

Peder Espen's avatar
Peder Espen committed
7
1. Connect to NTNU network (if you aren't there physically, use a VPN. Instructions: https://innsida.ntnu.no/wiki/-/wiki/English/Install+VPN)
8
2. Open two terminals
Peder Espen's avatar
Peder Espen committed
9
3. Navigate to the "project-3-it2810-group-32" folder.
Peder Espen's avatar
Peder Espen committed
10
3.  In terminal 1:
Eskild Brobak's avatar
Eskild Brobak committed
11
   cd server -> npm install -> npm start
Peder Espen's avatar
Peder Espen committed
12
5. In terminal 2:
Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
13
   cd client -> npm install -> npm start
Eskild Brobak's avatar
Eskild Brobak committed
14

15
16
Sometimes the server needs to be stopped (ctr+c) and run again (npm start)

Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
17
Client is running on localhost:3000 and server is running on localhost:5000
18

19
# How to run on gitpod
Eskild Brobak's avatar
Eskild Brobak committed
20

Peder Espen's avatar
Peder Espen committed
21
22
In gitpod everthing should set up automatically - but there are some issues with ports and access so it is better to clone and run locally. 
If you need to start the project again go to the root folder and run npm start
23

Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
24
Client is running on localhost:3000 and server is running on localhost:5000
25

Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
26
## If gitpod doesn't work
27

28
Clone and run locally.
29

Andreas Wilson's avatar
Andreas Wilson committed
30
31
# Overview

Eskild Brobak's avatar
Eskild Brobak committed
32
This project consists of a client part and a server part
Eskild Brobak's avatar
Eskild Brobak committed
33
34
35

# Client

Eskild Brobak's avatar
Eskild Brobak committed
36
37
## Technologies

Eskild Brobak's avatar
Eskild Brobak committed
38
39
40
41
42
The client is build on typescript, redux, bootstrap/reactstrap, react-router and axios.

## State management

State management is done by usage of both redux and react hooks.
Andreas Wilson's avatar
Andreas Wilson committed
43
Redux is used for handling the state of movies and pagination. For movies the states that are handled are an array
Eskild Brobak's avatar
Eskild Brobak committed
44
of all movies we currently are showing the user.
Eskild Brobak's avatar
Eskild Brobak committed
45

Andreas Wilson's avatar
Andreas Wilson committed
46
47
For states limited to local files we have used react hooks to simplify the program and to avoid
passing states around that are not necessary to keep in a global store.
Eskild Brobak's avatar
Eskild Brobak committed
48
49
50
51
52

## Content and functionality

1. Search - the user can do a search on movie titles. The search will query the backend via the API and the backend
   returns the matches.
Andreas Wilson's avatar
readme    
Andreas Wilson committed
53
54
2. Presentation of movies with pagination to prepare for handling of a large dataset and increase readability for the user.
   This is also done by using the API and the back-end.
Eskild Brobak's avatar
Eskild Brobak committed
55
3. By clicking on a movie more information of that movie is shown. This is done by querying for the specific movie ID in the database via the API.
Andreas Wilson's avatar
Andreas Wilson committed
56
57
4. Sorting and filtering - the user can sort all the movies by year, ascending or descending. The user can filter by up to three genres that are cumulative filtered. The filtering and sorting are also
   cumulative, as well as the search so if the user have entered a search in the search bar, a filter and a sorting all the data is sent to the api and handled backend.
Eskild Brobak's avatar
Eskild Brobak committed
58
5. User generated data that is saved to the backend. If a movie is added as a favorite, this choice is saved in the
Andreas Wilson's avatar
readme    
Andreas Wilson committed
59
60
   database (Clicking the little heart symbol on the front page will turn it red and save it as a favorite).
   The user can add also reviews to every movie which are saved to the database. There is no user-specific functionality
Eskild Brobak's avatar
Eskild Brobak committed
61
62
63
   in place so all reviews are anonymous.
6. Database is hosted on the virtual machine using MongoDB and contains a total of 20 movies.

Andreas Wilson's avatar
Andreas Wilson committed
64
65
66
67
68
69
70
71
72
73
74
# Server

## REST API

The server side is implemented using typescript, mongoDB and express.
A REST api is setup with a base url of /api/movies and have the following
functions

### Get requests

1. /api/movies/<id> => return a single movie if the id exist, else an error.
Andreas Wilson's avatar
readme    
Andreas Wilson committed
75
76
77
78
79
80
81
82
83
84
85
2. /api/movies
   If no options are added returns a json object with key totalCount and data-array
   where the movies objects are in the data-array
   Options can be added using regular syntax, ie /api/movies?title=Tenet&sortByYear=ascending
   Available options:
   title - filter title by partial match ignoring case
   year - filter year by partial match ignoring case
   sortByYear - can either be sortByYear=descending or ascending. Sorts by year
   genre - input as an array, ie ?genre[]=action&genre[]=drama - filter by all categories
   page - what page to show
   limit - how many results to return
Andreas Wilson's avatar
Andreas Wilson committed
86
87
88

### Put requests

Andreas Wilson's avatar
Andreas Wilson committed
89
1. /api/movies/<id> - creates a new movie object based on json data sent and
Andreas Wilson's avatar
Andreas Wilson committed
90
91
92
93
94
   updates an existing movie. Used to write comments and favorite movies to db.

## GraphQL

We decided not to implement GraphQL after learning about both REST API and GraphQL
Andreas Wilson's avatar
Andreas Wilson committed
95
96
since REST API was easier to implement and gave us all the functionality we needed
for this project.
Andreas Wilson's avatar
Andreas Wilson committed
97

Peder Espen's avatar
Peder Espen committed
98
99
100
101
GraphQL would be better suited for a bigger project where we had a lot more data to fetch.
Using GraphQL we would be able to fetch certain parts of the stored data, while with
REST we need to fetch the entire document and choose what we want in the front-end.

Andreas Wilson's avatar
Andreas Wilson committed
102
103
## Testing

Andreas Wilson's avatar
readme    
Andreas Wilson committed
104
For automatic end-2-end testing, we have used the cypress (https://www.cypress.io/) library
Andreas Wilson's avatar
Andreas Wilson committed
105
and made 5 tests that test different functionalities and navigation in the app.
Eskild Brobak's avatar
Eskild Brobak committed
106

Andreas Wilson's avatar
readme    
Andreas Wilson committed
107
We wanted to use the cypress framework cypress-react-unit-test to make unit tests, but we could not make it work as several errors was generated during this.
Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
108
We then tried other alternatives such as ensyme and jest, but it was hard making it work with typescript. The different tests we have made with cypress,
Eskild Brobak's avatar
Eskild Brobak committed
109
110
in our opinion, can be regarded as unit tests since they test do test the functionality of the app. An example would be that the last test successfully enters a review on the movie "Schindler's list"

Eskild Brobak's avatar
Eskild Brobak committed
111

Eskild Brobak's avatar
Eskild Brobak committed
112
**RUN CYPRESS TEST**
Andreas Wilson's avatar
readme    
Andreas Wilson committed
113

Eskild Brobak's avatar
Eskild Brobak committed
114
1. Open new terminal in client
Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
115
2. Type  "npm run e2e"
Eskild Brobak's avatar
Eskild Brobak committed
116
117
3. A window with cypress should open up
4. press "run all tests" in upright corner
Eskild Brobak's avatar
Eskild Brobak committed
118
119
120
121
122

If the above don't work:

1. Clone the repo
2. Open a terminal in client
Andreas Wågø Wilson's avatar
Andreas Wågø Wilson committed
123
3. Type "npm run e2e"
Eskild Brobak's avatar
Eskild Brobak committed
124
125
4. 3. A window with cypress should open up
5. press "run all tests" in upright corner
Eskild Brobak's avatar
Eskild Brobak committed
126

Andreas Wilson's avatar
readme    
Andreas Wilson committed
127
For some reason GitPod and Cypress don't work well together. The second solution will work, but requires a bit more work.
Eskild Brobak's avatar
Eskild Brobak committed
128
Here is a screenshot taken 30.10.2020 14:16:38, to prove that it works when running it locally if you don't want to clone the repo:
Eskild Brobak's avatar
Eskild Brobak committed
129

Eskild Brobak's avatar
Eskild Brobak committed
130
![Cypress test](Images/Cypress-test.png)
Eskild Brobak's avatar
Eskild Brobak committed
131

Andreas Wilson's avatar
readme    
Andreas Wilson committed
132
133
The fifth test checks if a user is able to add a review to a movie, but this will add a new review every time the test is run.
It is easy to remove these reviews after being implemented by running the mongodb query "cy.exec('db.movies.update( {Reviews: "This is a test"}, {\$unset: {Reviews: ""}})')",
Andreas Wilson's avatar
Andreas Wilson committed
134
but we wasn't able to implement this when running the test in cypress. Another work-around for deleting an review after each test run is to add a button to a review
Eskild Brobak's avatar
Eskild Brobak committed
135
which takes a movie-object, remove a comment/review and send it to an existing function called "updateMovie". We decided to not implement this last option
Eskild Brobak's avatar
Eskild Brobak committed
136
137
138
because we did not want a user to be able to delete another users review. Since we did not implement authorization for this kind of functionality, the result was
to just have every test add the same review every time it runs.

Eskild Brobak's avatar
Eskild Brobak committed
139
140
If you want to inspect the code, these tests are placed under client/cypress/integration/sample.spec.js.

Peder Espen's avatar
Peder Espen committed
141
142
143
144
145
146
We also attempted to make both Snapshot tests and Unit tests using the Enzyme library, as well as react-redux in order to test with our existing framework. 
Enzyme would primarily have allowed us to create "shallow" tests, where for example a snapshot would not need access to the entire tree to pass the test.
We also tried using redux-mock-store, which would have allowed us to create a mock store to use with our connected components to create unit tests. 
We did however not manage to use these frameworks in a good enough way, so we ended up dropping this idea. using react-redux would also have allowed us
to test specific Redux components like action or reducers.

Andreas Wilson's avatar
Andreas Wilson committed
147
148
# Git

Peder Espen's avatar
Peder Espen committed
149
150
We have used git actively and have used issues as a todo-list where we have assigned issues to ourselves
and to team-members. This is to keep control of what everyone is doing and what is missing. We have used branches to ensure that the code which is implemented
Andreas Wilson's avatar
readme    
Andreas Wilson committed
151
is thoroughly tested and working, before merging it to the master branch. By doing this the latest version (the master branch) will always function.
Andreas Wilson's avatar
Andreas Wilson committed
152
We have also made a link between the commits and the issues by referring to the issue by #<number>. In hindsight we realise that we could have used issues more frequently
Peder Espen's avatar
Peder Espen committed
153
and for smaller things that needed fixing, but it still worked well for our use case.