diff --git a/README.md b/README.md index 78cccd5..6a5d4d9 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,9 @@ Run the server: Your `.env` file should now look something like [example.env](https://github.com/ProgrammingBuddies/programmingbuddies-api/blob/develop/example.env) +- Optionally you can set the JWT token timeout + - `JWT_ACCESS_TOKEN_EXPIRES` - time in seconds + ### Testing - to run multiple tests just specify the directory which contains them for example `pipenv run pytest tests/` diff --git a/src/api/controllers/projectController.py b/src/api/controllers/projectController.py index c8d69f9..34269ca 100644 --- a/src/api/controllers/projectController.py +++ b/src/api/controllers/projectController.py @@ -1,60 +1,79 @@ -from api.models import db, Project, UserHasProject, ProjectLink, ProjectFeedback +from api.models import db, User, Project, UserHasProject, ProjectLink, ProjectFeedback class ProjectController: - session = db.session() + session = db.session # Project - def create_project(self, **kwargs): + def create_project(self, user_id, **kwargs): try: + user = User.query.filter_by(id=user_id).first() + + if user == None: + return None, "User not found", 404 + project = Project(**kwargs) - self.session.add(project) + + userHasProject = UserHasProject(role=1) + userHasProject.project = project + userHasProject.user = user + + self.session.add(userHasProject) self.session.commit() - return project + return project, "OK", 201 except: - return None + self.session.rollback() + return None, "Project creation failed", 400 - def update_project(self, id, **kwargs): - project = Project.query.filter_by(id=id).first() + def update_project(self, user_id, **kwargs): + if 'user_id' in kwargs: + return None, "Failed to update project. Request body can not specify user's id.", 400 - if project == None: - return None + if 'id' not in kwargs: + return None, "Failed to update project. Request body must specify project's id.", 400 - for key, value in kwargs.items(): - if not hasattr(project, key): - return None + user = User.query.filter_by(id=user_id).first() - for key, value in kwargs.items(): - setattr(project, key, value) - - db.session.commit() + if user == None: + return None, "User not found", 404 - return project - - def update_project(self, id, **kwargs): - project = Project.query.filter_by(id=id).first() + project = Project.query.filter_by(id=kwargs["id"]).first() if project == None: - return project + return None, "Project not found", 404 + + # Note that we are updating the id too, but to the same id because we used it to query the user with it + for key, value in kwargs.items(): + if not hasattr(project, key): + return None, f"Forbidden attribute '{key}'", 400 for key, value in kwargs.items(): setattr(project, key, value) db.session.commit() - return project + return project, "OK", 200 def get_project(self, **kwargs): project = Project.query.filter_by(**kwargs).first() - return project + if project: + return project, "OK", 200 + else: + return None, "Project not found", 404 def get_all_projects(self, **kwargs): all_projects = Project.query.all() - return all_projects + return all_projects, "OK", 200 + + def delete_project(self, user_id, id): + + userHasProject = UserHasProject.query.filter_by(user_id=user_id, project_id=id).first() + # TODO: verify that the user owns the project (or has neccessary rights) + if not userHasProject: + return None, "Failed to delete project. Current user does not belong to specified project, or the project does not exist.", 404 - def delete_project(self, id): # Remove all project's links for link in ProjectLink.query.filter_by(project_id=id).all(): db.session.delete(link) @@ -66,84 +85,99 @@ def delete_project(self, id): project = Project.query.filter_by(id=id).first() if project == None: - return project + # TODO: db.session.rollback? + return None, "Project not found", 404 db.session.delete(project) db.session.commit() - return project + return project, "OK", 200 # Project Link - def create_link(self, project_id, **kwargs): + def create_link(self, user_id, **kwargs): try: - link = ProjectLink(project_id=project_id, **kwargs) - self.session.add(link) - self.session.commit() + if "project_id" in kwargs and "name" in kwargs and "url" in kwargs and len(kwargs) == 3: + if kwargs["project_id"] is None or kwargs["name"] is None or kwargs["url"] is None: + return None, "Arguments can't be empty", 400 - return link + link = ProjectLink(**kwargs) + self.session.add(link) + self.session.commit() + + return link, "OK", 201 + else: + return None, "Forbidden attributes used in request. Only 'project_id', 'name' and 'url' allowed.", 400 except: self.session.rollback() - return None - - def update_link(self, project_id, link_id, **kwargs): - link = ProjectLink.query.filter_by(project_id=project_id, id=link_id).first() + return None, "Failed to create project link.", 400 - if link == None: - return None + def update_link(self, user_id, **kwargs): + if "project_id" in kwargs and "id" in kwargs and len(kwargs) >= 2: + if kwargs["project_id"] is None or kwargs["id"] is None: + return None, "Arguments can't be empty", 400 - for key, value in kwargs.items(): - if not hasattr(link, key): - return None + link = ProjectLink.query.filter_by(project_id=kwargs["project_id"], id=kwargs["id"]).first() - for key, value in kwargs.items(): - setattr(link, key, value) + if link == None: + return None, "Failed to update project link. Project link not found.", 404 - db.session.commit() + for key, value in kwargs.items(): + if not hasattr(link, key): + return None, f"Failed to update project link. Forbidden attribute '{key}'.", 400 - return link + for key, value in kwargs.items(): + setattr(link, key, value) - def get_all_links(self, project_id): - all_links = ProjectLink.query.filter_by(project_id=project_id).all() + db.session.commit() - return all_links + return link, "OK", 200 + else: + return None, "Forbidden attributes used in request. Only 'project_id', 'id', 'name' and 'url' allowed.", 400 - def delete_link(self, project_id, link_id): - link = ProjectLink.query.filter_by(project_id=project_id, id=link_id).first() + def delete_link(self, user_id, link_id): + link = ProjectLink.query.filter_by(id=link_id).first() if link == None: - return None + return None, "Failed to delete project link. Project link not found.", 404 db.session.delete(link) db.session.commit() - return link + return link, "OK", 200 # Project Feedback - def create_feedback(self, project_id, **kwargs): + def create_feedback(self, author_id, **kwargs): + if 'project_id' not in kwargs: + return None, "Failed to create feedback. Request body must specify feedback's project_id.", 400 + try: - feedback = ProjectFeedback(project_id=project_id, **kwargs) - self.session.add(feedback) - self.session.commit() + if "project_id" in kwargs and "rating" in kwargs and "description" in kwargs and len(kwargs) == 3: + if kwargs["project_id"] is None or kwargs["rating"] is None or kwargs["description"] is None: + return None, "Arguments can't be empty", 400 - return feedback + feedback = ProjectFeedback(author_id=author_id, **kwargs) + self.session.add(feedback) + self.session.commit() + + return feedback, "OK", 201 + else: + return None, "Forbidden attributes used in request. Only 'project_id', 'rating' and 'description' allowed.", 400 except: self.session.rollback() - return None - - def get_all_feedbacks(self, project_id): - all_feedbacks = ProjectFeedback.query.filter_by(project_id=project_id).all() + return None, "Failed to create project feedback.", 400 - return all_feedbacks - - def delete_feedback(self, project_id, feedback_id): - feedback = ProjectFeedback.query.filter_by(project_id=project_id, id=feedback_id).first() + def delete_feedback(self, author_id, feedback_id): + feedback = ProjectFeedback.query.filter_by(id=feedback_id).first() if feedback == None: - return None + return None, "Failed to delete project feedback. Project feedback not found.", 404 + + if feedback.author_id != author_id: + return None, "Failed to delete project feedback. Cannot delete project feedback that you did not create.", 400 db.session.delete(feedback) db.session.commit() - return feedback + return feedback, "OK", 200 projectController = ProjectController() diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index da4f01e..24bd906 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -4,7 +4,7 @@ from flask import jsonify class UserController: - session = db.session() + session = db.session # User def create_user(self, **kwargs): @@ -16,17 +16,17 @@ def create_user(self, **kwargs): return user, "OK", 200 except: self.session.rollback() - return None, "Forbidden Attributes", 400 + return None, "Forbidden attributes", 400 def update_user(self, id, **kwargs): user = User.query.filter_by(id=id).first() if user == None: - return None, "user not found", 404 + return None, "User not found", 404 for key, value in kwargs.items(): if not hasattr(user, key): - return None, "forbidden attribute", 400 + return None, f"Forbidden attribute '{key}'", 400 for key, value in kwargs.items(): setattr(user, key, value) @@ -39,15 +39,10 @@ def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() if user is None: - return None, "User Not Found", 404 + return None, "User not found", 404 return user, "OK", 200 - def get_all_users(self, **kwargs): - all_users = User.query.all() - - return all_users - def delete_user(self, id): # Remove all user's links for link in UserLink.query.filter_by(user_id=id).all(): @@ -60,7 +55,7 @@ def delete_user(self, id): user = User.query.filter_by(id=id).first() if user == None: - return None, "user not found", 404 + return None, "User not found", 404 db.session.delete(user) db.session.commit() @@ -81,7 +76,7 @@ def create_link(self, user_id, **kwargs): return None, "Forbidden attributes used in request. only name and url allowed.", 400 except: self.session.rollback() - return None, "link creation failed", 500 + return None, "Link creation failed", 500 def update_link(self, user_id, **kwargs): if not 'id' in kwargs: @@ -108,7 +103,7 @@ def get_all_links(self, user_id): user = User.query.filter_by(id=user_id).first() if user is None: return None, "User not found", 404 - + return user.links, "OK", 200 def delete_link(self, user_id, **kwargs): diff --git a/src/api/models/projectFeedbackModel.py b/src/api/models/projectFeedbackModel.py index 19f484e..db1c7dd 100644 --- a/src/api/models/projectFeedbackModel.py +++ b/src/api/models/projectFeedbackModel.py @@ -2,7 +2,7 @@ class ProjectFeedback(db.Model): id = db.Column(db.Integer, primary_key=True) - user_id = db.Column(db.Integer, db.ForeignKey('user.id')) + author_id = db.Column(db.Integer, db.ForeignKey('user.id')) project_id = db.Column(db.Integer, db.ForeignKey('project.id')) rating = db.Column(db.Integer, nullable=False) description = db.Column(db.String(255), nullable=True) @@ -10,7 +10,7 @@ class ProjectFeedback(db.Model): def as_dict(self): obj_d = { 'id': self.id, - 'user_id': self.user_id, + 'author_id': self.author_id, 'project_id': self.project_id, 'rating': self.rating, 'description': self.description, diff --git a/src/api/views/projectView.py b/src/api/views/projectView.py index 587a6f4..b5c8e25 100644 --- a/src/api/views/projectView.py +++ b/src/api/views/projectView.py @@ -1,12 +1,17 @@ from flask import request, jsonify +from flask_jwt_extended import get_jwt_identity, jwt_required from api import app +from api.utils import wrap_response, body_required from api.controllers import projectController # Project -@app.route("/projects", methods=['POST']) +@app.route("/project", methods=['POST']) +@jwt_required +@body_required def create_project(): """ Create project + Current user creates project --- tags: - Project @@ -32,16 +37,16 @@ def create_project(): description: Description of the project languages: type: string - description: List of programming languages the project uses + description: (Optional) List of programming languages the project uses development_status: type: integer description: Development status of the project creation_date: type: string - description: Creation date of the project + description: (Optional) Creation date of the project release_date: type: string - description: Release date of the project + description: (Optional) Release date of the project repository: type: string description: Url of the project's repository @@ -65,28 +70,22 @@ def create_project(): description: Project created successfully 400: description: Failed to create project + 404: + description: User doesn't exist """ - project = projectController.create_project(**request.get_json()) - - if project == None: - return "Failed to create project.", 400 - else: - return jsonify(project.as_dict()), 201 + return wrap_response(*projectController.create_project(user_id=get_jwt_identity(), **request.get_json())) -@app.route("/projects/", methods=['PUT']) -def update_project(id): +@app.route("/project", methods=['PUT']) +@jwt_required +@body_required +def update_project(): """ Update project - Updates project with `id` using the data in request body + Updates current user's project with the data in request body --- tags: - Project parameters: - - in: path - name: id - type: integer - required: true - description: Id of project to update - in: body name: Project required: true @@ -98,18 +97,15 @@ def update_project(id): description: Project updated successfully 400: description: Failed to update project + 404: + description: Current user or requested project not found """ - if 'id' in request.get_json(): - return "Failed to update project. Request body can not specify project's id.", 501 - - project = projectController.update_project(id, **request.get_json()) + if "user_id" in request.get_json(): + return wrap_response(None, "Failed to update project. Request body must not contain 'user_id'.", 400) - if project == None: - return "Failed to update project.", 400 - else: - return jsonify(project.as_dict()), 200 + return wrap_response(*projectController.update_project(user_id=get_jwt_identity(), **request.get_json())) -@app.route("/projects/", methods=['GET']) +@app.route("/project/", methods=['GET']) def get_project(id): """ Get project @@ -129,14 +125,9 @@ def get_project(id): 404: description: Project not found """ - project = projectController.get_project(id=id) + return wrap_response(*projectController.get_project(id=id)) - if project: - return jsonify(project.as_dict()), 200 - else: - return "", 404 - -@app.route("/projects", methods=['GET']) +@app.route("/project/all", methods=['GET']) def get_all_projects(): """ Get all projects @@ -148,17 +139,14 @@ def get_all_projects(): 200: description: List of projects """ - all_projects = projectController.get_all_projects() - - projects = [ project.as_dict() for project in all_projects ] + return wrap_response(*projectController.get_all_projects()) - return jsonify(projects), 200 - -@app.route("/projects/", methods=['DELETE']) +@app.route("/project/", methods=['DELETE']) +@jwt_required def delete_project(id): """ Delete project - Deletes project with `id` + Deletes current user's project with the `id` --- tags: - Project @@ -172,18 +160,17 @@ def delete_project(id): 200: description: Project deleted successfully 400: - description: Project not found + description: Failed to delete project + 404: + description: Current user is not a member of requested project or the project was not found """ - project = projectController.delete_project(id) - - if project: - return "", 202 - else: - return "", 404 + return wrap_response(*projectController.delete_project(user_id=get_jwt_identity(), id=id)) # Project Link -@app.route("/projects//links", methods=['POST']) -def create_project_link(project_id): +@app.route("/project/link", methods=['POST']) +@jwt_required +@body_required +def create_project_link(): """ Create project link --- @@ -218,35 +205,22 @@ def create_project_link(project_id): 400: description: Failed to create project link """ - if 'project_id' in request.get_json(): - return "Failed to create project link. Request body can not specify link's project_id.", 400 + if "user_id" in request.get_json(): + return wrap_response(None, "Failed to create project link. Request body must not contain 'user_id'.", 400) - link = projectController.create_link(project_id, **request.get_json()) + return wrap_response(*projectController.create_link(user_id=get_jwt_identity(), **request.get_json())) - if link == None: - return "Failed to create project link.", 400 - else: - return jsonify(link.as_dict()), 201 - -@app.route("/projects//links/", methods=['PUT']) -def update_project_link(project_id, link_id): +@app.route("/project/link", methods=['PUT']) +@jwt_required +@body_required +def update_project_link(): """ Update project link - Updates project link with `project_id` and `link_id` using the data in request body + Updates project link with data in the request body --- tags: - ProjectLink parameters: - - in: path - name: project_id - type: integer - required: true - description: Id of the project - - in: path - name: link_id - type: integer - required: true - description: Id of the project link to update - in: body name: ProjectLink required: true @@ -258,57 +232,24 @@ def update_project_link(project_id, link_id): description: Project link updated successfully 400: description: Failed to update project link + 404: + description: Project link not found """ - if 'project_id' in request.get_json(): - return "Failed to update project link. Request body can not specify link's project_id.", 400 - elif 'link_id' in request.get_json(): - return "Failed to update project link. Request body can not specify link's link_id.", 400 - - link = projectController.update_link(project_id, link_id, **request.get_json()) - - if link == None: - return "Failed to update project link.", 400 - else: - return jsonify(link.as_dict()), 200 - -@app.route("/projects//links", methods=['GET']) -def get_all_project_links(project_id): - """ - Get all project links - Retreives all project links with `project_id` - --- - tags: - - ProjectLink - parameters: - - in: path - name: project_id - type: integer - required: true - description: Id of the project - responses: - 200: - description: List of project links - """ - all_links = projectController.get_all_links(project_id) + if "user_id" in request.get_json(): + return wrap_response(None, "Failed to update project link. Request body must not contain 'user_id'.", 400) - links = [ link.as_dict() for link in all_links ] + return wrap_response(*projectController.update_link(user_id=get_jwt_identity(), **request.get_json())) - return jsonify(links), 200 - -@app.route("/projects//links/", methods=['DELETE']) -def delete_project_link(project_id, link_id): +@app.route("/project/link/", methods=['DELETE']) +@jwt_required +def delete_project_link(link_id): """ Delete project link - Deletes project link with `project_id` and `link_id` + Deletes project link with `link_id` --- tags: - ProjectLink parameters: - - in: path - name: project_id - type: integer - required: true - description: Id of the project - in: path name: link_id type: integer @@ -317,19 +258,18 @@ def delete_project_link(project_id, link_id): responses: 200: description: Project link deleted successfully + 400: + description: Failed to delete project link 404: description: Project link not found """ - link = projectController.delete_link(project_id, link_id) - - if link == None: - return "", 404 - else: - return "", 200 + return wrap_response(*projectController.delete_link(user_id=get_jwt_identity(), link_id=link_id)) # Project Feedback -@app.route("/projects//feedbacks", methods=['POST']) -def create_project_feedback(project_id): +@app.route("/project/feedback", methods=['POST']) +@jwt_required +@body_required +def create_project_feedback(): """ Create project feedback --- @@ -339,7 +279,7 @@ def create_project_feedback(project_id): - in: body name: ProjectFeedback required: true - description: Project feedback object containing data to update + description: Project feedback object containing data to create schema: $ref: "#/definitions/ProjectFeedback" definitions: @@ -349,9 +289,9 @@ def create_project_feedback(project_id): id: type: integer description: Id of the project feedback. This property will be assigned a value returned by the database - user_id: + author_id: type: integer - description: Id of the user + description: Id of the author (user) project_id: type: integer description: Id of the project @@ -367,54 +307,21 @@ def create_project_feedback(project_id): 400: description: Failed to create project feedback """ - if 'project_id' in request.get_json(): - return "Failed to create feedback. Request body can not specify feedback's project_id.", 400 - - feedback = projectController.create_feedback(project_id, **request.get_json()) - - if feedback == None: - return "Failed to create feedback.", 400 - else: - return jsonify(feedback.as_dict()), 201 - -@app.route("/projects//feedbacks", methods=['GET']) -def get_all_project_feedbacks(project_id): - """ - Get all project feedbacks - Retreives all project feedbacks with `project_id` - --- - tags: - - ProjectFeedback - parameters: - - in: path - name: project_id - type: integer - required: true - description: Id of the project - responses: - 200: - description: List of project feedbacks - """ - all_feedbacks = projectController.get_all_feedbacks(project_id) + if "author_id" in request.get_json(): + return wrap_response(None, "Failed to create project feedback. Request body must not contain 'author_id'.", 400) - feedbacks = [ feedback.as_dict() for feedback in all_feedbacks ] + return wrap_response(*projectController.create_feedback(author_id=get_jwt_identity(), **request.get_json())) - return jsonify(feedbacks), 200 - -@app.route("/projects//feedbacks/", methods=['DELETE']) -def delete_project_feedback(project_id, feedback_id): +@app.route("/project/feedback/", methods=['DELETE']) +@jwt_required +def delete_project_feedback(feedback_id): """ Delete project feedback - Deletes project feedback with `project_id` and `feedback_id` + Deletes project feedback with `feedback_id` --- tags: - ProjectFeedback parameters: - - in: path - name: project_id - type: integer - required: true - description: Id of the project - in: path name: feedback_id type: integer @@ -423,12 +330,9 @@ def delete_project_feedback(project_id, feedback_id): responses: 200: description: Project feedback deleted successfully + 400: + description: Failed to delete project feedback 404: description: Project feedback not found """ - feedback = projectController.delete_feedback(project_id, feedback_id) - - if feedback == None: - return "", 404 - else: - return "", 200 + return wrap_response(*projectController.delete_feedback(author_id=get_jwt_identity(), feedback_id=feedback_id)) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index c21143e..c9b77e8 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -88,7 +88,7 @@ def delete_user(): 404: description: User the token belonged to doesn't exist anymore """ - + return wrap_response(*userController.delete_user(get_jwt_identity())) # User Link @@ -152,7 +152,7 @@ def update_user_link(): description: (optional) Name of the user link url: type: string - description: (optional)Url of the user link + description: (optional) Url of the user link responses: 200: description: User link updated successfully diff --git a/tests/__init__.py b/tests/__init__.py index 56f3d94..25d093a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -6,6 +6,6 @@ from api import app from api.models import db -from api.models import User, Project, UserFeedback, ProjectFeedback, UserLink, ProjectLink +from api.models import User, Project, UserHasProject, UserFeedback, ProjectFeedback, UserLink, ProjectLink sys.path.insert(0, os.getcwd()+'/tests') diff --git a/tests/api/__init__.py b/tests/api/__init__.py index bd7fb7c..db64e86 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -11,7 +11,17 @@ """ from flask_jwt_extended import create_access_token -from tests import db, Project, User, UserLink, ProjectLink, UserFeedback +from tests import db, Project, User, UserHasProject, UserLink, ProjectLink, UserFeedback, ProjectFeedback + +""" Create relationship between user and project """ +def user_join_project_for_test_cases(user, project): + userHasProject = UserHasProject(role=1) + userHasProject.project = Project.query.filter_by(id=project["id"]).first() + userHasProject.user = user + # This line is not needed for some reason + # SQLAlchemy is doing some magic and I don't know shit about fuck + #user.projects.append(userHasProject) + db.session.commit() def create_project_for_test_cases(data): new_project = Project(**data) @@ -31,6 +41,13 @@ def create_project_link_for_test_cases(data): return new_project_link.as_dict() +def create_project_feedback_for_test_cases(data): + new_project_feedback = ProjectFeedback(**data) + db.session.add(new_project_feedback) + db.session.commit() + + return new_project_feedback.as_dict() + def create_access_token_for_test_cases(data): new_user = User(**data) db.session.add(new_user) diff --git a/tests/api/views/test_projectView.py b/tests/api/views/test_projectView.py index eb328d4..4d58672 100644 --- a/tests/api/views/test_projectView.py +++ b/tests/api/views/test_projectView.py @@ -1,82 +1,109 @@ from tests.conftest import client -from tests import db, Project, ProjectLink -from tests.api import create_project_for_test_cases, create_project_link_for_test_cases +from tests import db, Project, ProjectLink, ProjectFeedback +from tests.api import create_project_for_test_cases, create_project_link_for_test_cases, create_project_feedback_for_test_cases, create_access_token_for_test_cases, user_join_project_for_test_cases class TestProjectView(object): - valid_data = { + # valid data for user creation + valid_user_data = { + 'name': 'L Jone', + 'bio': 'coding...', + 'languages': 'FR', + 'interests': 'Nothing', + 'location': 'X', + 'occupation': 'cashier' + } + + valid_project_data = { 'name': 'PB api', 'description': 'A cool project', + 'development_status': 1, 'repository': 'http://github.xy.com' } + # Project def test_create_project(self, client): - response = client.post('/projects', json={"name": "Project"}) + token, _ = create_access_token_for_test_cases(self.valid_user_data) + + response = client.post('/project', headers={"Authorization": f"Bearer {token}"}, json={"name": "Project"}) assert response.status_code == 400 - response = client.post('/projects', json=self.valid_data) - assert response.status_code == 201 + response = client.post('/project', headers={"Authorization": f"Bearer {token}"}) + assert response.status_code == 400 - # response = client.post('/projects') - # assert response.status_code == 400 + response = client.post('/project') + assert response.status_code == 401 + + response = client.post('/project', headers={"Authorization": f"Bearer {token}"}, json=self.valid_project_data) + assert response.status_code == 201 def test_update_project(self, client): + token, _ = create_access_token_for_test_cases(self.valid_user_data) # project id doesn't exist - response = client.post('/projects/0', json={'name': 'Updated PB'}) - - # notice: should return 404 when doesen't exist insted of 400 + response = client.put('/project', headers={"Authorization": f"Bearer {token}"}, json={'id': 0, 'name': 'Updated PB'}) assert response.status_code == 404 - project_id = create_project_for_test_cases(self.valid_data) - response = client.post('/projects/{}'.format(project_id), json={'description': 'updated desc'}) + project = create_project_for_test_cases(self.valid_project_data) + project_id = project["id"] + + response = client.put('/project', headers={"Authorization": f"Bearer {token}"}, json={'id': project_id, 'description': 'updated desc'}) project = Project.query.filter_by(id=project_id).first() assert project.description == 'updated desc' def test_delete_project(self, client): - response = client.delete('/projects/0') + token, user = create_access_token_for_test_cases(self.valid_user_data) + + response = client.delete('/project/{}'.format(0), headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 404 - project1 = create_project_for_test_cases(self.valid_data) + project1 = create_project_for_test_cases(self.valid_project_data) + user_join_project_for_test_cases(user, project1) - self.valid_data["name"] = "p2 name" - project2 = create_project_for_test_cases(self.valid_data) + self.valid_project_data["name"] = "p2 name" + project2 = create_project_for_test_cases(self.valid_project_data) + user_join_project_for_test_cases(user, project2) - response = client.delete('/projects/{}'.format(project1["id"])) - assert response.status_code == 202 + response = client.delete('/project/{}'.format(project1["id"]), headers={"Authorization": f"Bearer {token}"}) + assert response.status_code == 200 def test_get_project(self, client): - response = client.get('/projects/{}'.format(0)) + response = client.get('/project/{}'.format(0)) assert response.status_code == 404 - project = create_project_for_test_cases(self.valid_data) - response = client.get('/projects/{}'.format(project["id"])) + project = create_project_for_test_cases(self.valid_project_data) + response = client.get('/project/{}'.format(project["id"])) assert response.status_code == 200 - assert response.get_json()["name"] == project["name"] + assert response.get_json()["data"]["name"] == project["name"] def test_get_all_projects(self, client): - project1 = create_project_for_test_cases(self.valid_data) + project1 = create_project_for_test_cases(self.valid_project_data) - self.valid_data["name"] = "allproject2" - project2 = create_project_for_test_cases(self.valid_data) - response = client.get('/projects') + self.valid_project_data["name"] = "allproject2" + project2 = create_project_for_test_cases(self.valid_project_data) + response = client.get('/project/all') assert response.status_code == 200 r = response.get_json() - assert [r[0]["name"], r[1]["name"]] == [project1["name"], project2["name"]] + assert [r["data"][0]["name"], r["data"][1]["name"]] == [project1["name"], project2["name"]] + # Project Link def test_create_project_link(self, client): - project = create_project_for_test_cases(self.valid_data) - url = '/projects/{}/links'.format(project["id"]) + token, _ = create_access_token_for_test_cases(self.valid_user_data) - response = client.post(url, json={"user_id": 0}) + project = create_project_for_test_cases(self.valid_project_data) + url = '/project/link' + + response = client.post(url, headers={"Authorization": f"Bearer {token}"}, json={"user_id": 0}) assert response.status_code == 400 - response = client.post(url, json={"name": "Main link", "url": "http://main.link"}) + response = client.post(url, headers={"Authorization": f"Bearer {token}"}, json={"project_id": project["id"], "name": "Main link", "url": "http://main.link"}) assert response.status_code == 201 def test_update_project_link(self, client): - p1 = create_project_for_test_cases(self.valid_data) + token, _ = create_access_token_for_test_cases(self.valid_user_data) + + p1 = create_project_for_test_cases(self.valid_project_data) p1_link = create_project_link_for_test_cases( { "name": "Plink", @@ -84,22 +111,27 @@ def test_update_project_link(self, client): "project_id": p1["id"] }) - url = '/projects/{0}/links/{1}' + url = '/project/link' - # notice: this shouldn't give 500 error - # response = client.post(url.format(p1["id"], 0)) - # assert response.status_code == 404 + response = client.put(url, headers={"Authorization": f"Bearer {token}"}, json={"project_id": p1["id"], "id": 0}) + assert response.status_code == 404 - # notice: this shouldn't give 500 error - # response = client.post(url.format(0, p1_link["id"])) - # assert response.status_code == 404 + response = client.put(url, headers={"Authorization": f"Bearer {token}"}, json={"project_id": 0, "id": p1_link["id"]}) + assert response.status_code == 404 - response = client.post(url.format(p1["id"], p1_link["id"]), json={"name": "Nlink"}) + response = client.put(url, headers={"Authorization": f"Bearer {token}"}, json={"project_id": p1["id"], "id": p1_link["id"], "name": "Nlink"}) assert response.status_code == 200 - assert response.get_json()["name"] == "Nlink" + assert response.get_json()["data"]["name"] == "Nlink" + + def test_delete_project_link(self, client): + token, _ = create_access_token_for_test_cases(self.valid_user_data) + + url = '/project/link/{}' - def test_get_all_project_links(self, client): - p1 = create_project_for_test_cases(self.valid_data) + response = client.delete(url.format(0), headers={"Authorization": f"Bearer {token}"}) + assert response.status_code == 404 + + p1 = create_project_for_test_cases(self.valid_project_data) p_link1 = create_project_link_for_test_cases( { "name": "Plink", @@ -113,33 +145,53 @@ def test_get_all_project_links(self, client): "project_id": p1["id"] }) - response = client.get('/projects/{}/links'.format(p1["id"])) + + response = client.delete(url.format(p_link1["id"]), headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 200 - assert response.get_json() == [p_link1, p_link2] + items = ProjectLink.query.all() + assert len(items) == 1 + assert items[0].name == "Other" - def test_delete_project_link(self, client): - url = '/projects/{0}/links/{1}' + # Projet Feedback + def test_create_project_feedback(self, client): + token, user = create_access_token_for_test_cases(self.valid_user_data) + + project = create_project_for_test_cases(self.valid_project_data) + url = '/project/feedback' + + response = client.post(url, headers={"Authorization": f"Bearer {token}"}, json={"user_id": 0}) + assert response.status_code == 400 + + response = client.post(url, headers={"Authorization": f"Bearer {token}"}, json={"project_id": project["id"], "rating": 3, "description": "A feedback"}) + assert response.status_code == 201 + + def test_delete_project_feedback(self, client): + token, user = create_access_token_for_test_cases(self.valid_user_data) + + url = '/project/feedback/{}' - response = client.delete(url.format(0, 0)) + response = client.delete(url.format(0), headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 404 - p1 = create_project_for_test_cases(self.valid_data) - p_link1 = create_project_link_for_test_cases( + p1 = create_project_for_test_cases(self.valid_project_data) + p_feedback1 = create_project_feedback_for_test_cases( { - "name": "Plink", - "url": "https://xll.com", - "project_id": p1["id"] + "rating": 1, + "description": "A feedback", + "project_id": p1["id"], + "author_id": user.id }) - p_link2 = create_project_link_for_test_cases( + p_feedback2 = create_project_feedback_for_test_cases( { - "name": "Other", - "url": "https://pp.com", - "project_id": p1["id"] + "rating": 5, + "description": "Other", + "project_id": p1["id"], + "author_id": user.id }) - response = client.delete(url.format(p1["id"], p_link1["id"])) + response = client.delete(url.format(p_feedback1["id"]), headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 200 - items = ProjectLink.query.all() + items = ProjectFeedback.query.all() assert len(items) == 1 - assert items[0].name == "Other" + assert items[0].description == "Other" diff --git a/tests/api/views/test_userView.py b/tests/api/views/test_userView.py index ad6908d..72a3c75 100644 --- a/tests/api/views/test_userView.py +++ b/tests/api/views/test_userView.py @@ -15,7 +15,6 @@ class TestUserView(object): 'occupation': 'cashier' } - def test_update_user(self, client): token, _ = create_access_token_for_test_cases(self.valid_data) @@ -36,51 +35,20 @@ def test_delete_user(self, client): response = client.delete('/user', headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 404 - + def test_get_user(self, client): token, user = create_access_token_for_test_cases(self.valid_data) - + response = client.get('/user', headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 200 assert response.get_json() == {"data": user.as_dict(), "msg": "OK"} delete_user_for_test_cases(user) - + response = client.get('/user', headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 404 - - - - def test_get_all_users(self, client): - create_user_for_test_cases(self.valid_data) - - self.valid_data = { - 'name': 'Valid', - 'bio': 'new', - 'languages': 'DE', - 'interests': 'e', - 'location': 'nowhere', - 'occupation': 'cashier2.1' - } - - create_user_for_test_cases(self.valid_data) - - response = client.get('/users') - assert response.status_code == 200 - - users_list = User.query.all() - users_dict = [users_list[0].as_dict(), users_list[1].as_dict()] - assert response.get_json() == [users_list[0].as_dict(), users_list[1].as_dict()] - - db.session.delete(users_list[0]) - db.session.commit() - - response = client.get('/users') - assert response.status_code == 200 - assert response.get_json() == [users_dict[1]] - def test_create_user_link(self, client): token, user = create_access_token_for_test_cases(self.valid_data) url = '/user/link' diff --git a/tests/runtests.py b/tests/runtests.py index 82a6c8b..70d7f78 100644 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -1,6 +1,6 @@ response = """ -Use: pipenv run pytest src/tests/ +Usage: pipenv run pytest tests/ """