Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Implement API route for "Project" section #40

Merged
merged 5 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 122 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from flask import Flask, jsonify, request
from models import Experience, Education, Skill, User
from models import Experience, Education, Project, Skill, User
from utils import get_suggestion, check_phone_number, correct_spelling


Expand Down Expand Up @@ -39,7 +39,19 @@
"example-logo.png",
)
],
"skill": [Skill("Python", "1-2 Years", "example-logo.png")],
"skill": [
Skill("Python",
"1-2 Years",
"example-logo.png")
],
"project": [
Project(
title="Sample Project",
description="A sample project",
technologies=["Python", "Flask"],
link="https://github.com/username/sample-project"
)
]
}


Expand Down Expand Up @@ -168,6 +180,114 @@ def skill():
return jsonify({})


@app.route('/resume/project', methods=['GET', 'POST', 'PUT', 'DELETE'])
def project():
'''
Handles Project requests
'''
def validate_id(project_id):
'''
Validates the id
'''
if project_id is None:
raise ValueError("Missing id")

if not project_id.isdigit():
raise ValueError("Invalid id")

# check if the id is within the range of the project list
int_id = int(project_id)
if int_id < 0 or int_id >= len(data['project']):
raise ValueError("Project not found")

return int_id

def get_project(project_id):
'''
Get project by id
'''
if project_id is not None:
try:
project_id = validate_id(project_id)
return jsonify(data['project'][project_id]), 200
except ValueError as error:
return jsonify({"error": str(error)}), 400

return jsonify([
{**project.__dict__, "id": str(index)}
for index, project in enumerate(data['project'])
]), 200

def add_project(body):
'''
Add project
'''
mandatory_fields = ['title', 'description', 'technologies', 'link']
missing_fields = [field for field in mandatory_fields if field not in body]

if missing_fields:
return jsonify({"error": f"Missing fields: {', '.join(missing_fields)}"}), 400

new_project = Project(
body['title'],
body['description'],
body['technologies'],
body['link']
)
data['project'].append(new_project)

return jsonify({**new_project.__dict__, "id": str(len(data['project']) - 1)}), 201

def edit_project(project_id, body):
'''
Edit project
'''
try:
project_id = validate_id(project_id)
except ValueError as error:
return jsonify({"error": str(error)}), 400

for key, value in body.items():
if hasattr(data['project'][project_id], key):
setattr(data['project'][project_id], key, value)
else:
return jsonify({"error": f"invalid field: {key}"}), 400

return jsonify({**data['project'][project_id].__dict__, "id": str(project_id)}), 200

def delete_project(project_id):
'''
Delete project
'''
try:
project_id = validate_id(project_id)
except ValueError as error:
return jsonify({"error": str(error)}), 400

del data['project'][project_id]
return jsonify({}), 204

if request.method == 'GET':
project_id = request.args.get('id', None)
return get_project(project_id)

if request.method == 'POST':
body = request.get_json()
return add_project(body)

if request.method == 'PUT':
project_id = request.args.get('id', None)
body = request.get_json()

return edit_project(project_id, body)

if request.method == 'DELETE':
project_id = request.args.get('id', None)

return delete_project(project_id)

return jsonify({"error": "Unsupported request method"}), 405

@app.route("/resume/spellcheck", methods=["POST"])
def spellcheck():
"""
Expand Down
11 changes: 11 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
'''

from dataclasses import dataclass
from typing import List

@dataclass
class User:
Expand Down Expand Up @@ -49,3 +50,13 @@ class Skill:
name: str
proficiency: str
logo: str

@dataclass
class Project:
'''
Project Class
'''
title: str
description: str
technologies: List[str]
link: str
82 changes: 82 additions & 0 deletions test_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,88 @@ def test_skill():
assert response.json["skills"][item_id] == example_skill


def test_get_project():
'''
Test the get_project function

Check that it returns a list of projects
'''
response = app.test_client().get('/resume/project')
assert response.status_code == 200
assert isinstance(response.json, list)

def test_add_project():
'''
Test the add_project function

Check that it returns the new project
Check that it returns an error when missing fields
'''
new_project = {
'title': 'Sample Project',
'description': 'A sample project',
'technologies': ['Python', 'Flask'],
'link': 'https://github.com/username/sample-project'
}
response = app.test_client().post('/resume/project', json=new_project)
assert response.status_code == 201
assert response.json == {**new_project, 'id': '1'}

new_project.pop('title')
response = app.test_client().post('/resume/project', json=new_project)
assert response.status_code == 400
assert response.json == {'error': 'Missing fields: title'}

def test_edit_project():
'''
Test the edit_project function

Check that it returns the updated project
Check that it returns an error when the project id is invalid
'''
new_project = {
'title': 'Sample Project',
'description': 'A sample project',
'technologies': ['Python', 'Flask'],
'link': 'https://github.com/username/sample-project'
}
new_project_id = app.test_client().post('/resume/project', json=new_project).json['id']
new_project['title'] = 'New Project'
new_project['description'] = 'A new project'
new_project['technologies'] = ['Python', 'Flask', 'Docker']

response = app.test_client().\
put('/resume/project', json=new_project, query_string={'id': new_project_id})

assert response.status_code == 200
assert response.json == {**new_project, 'id': new_project_id}

response = app.test_client().\
put('/resume/project', json=new_project, query_string={'id': 'invalid-id'})
assert response.status_code == 400
assert response.json == {'error': 'Invalid id'}

def test_delete_project():
'''
Test the delete_project function

Check that it returns a 204 status code
Check that it returns an error when the project id is invalid
'''
new_project = {
'title': 'Sample Project',
'description': 'A sample project',
'technologies': ['Python', 'Flask'],
'link': 'https://github.com/username/sample-project'
}
new_project_id = app.test_client().post('/resume/project', json=new_project).json['id']
response = app.test_client().delete('/resume/project', query_string={'id': new_project_id})
assert response.status_code == 204

response = app.test_client().delete('/resume/project', query_string={'id': 'invalid-id'})
assert response.status_code == 400
assert response.json == {'error': 'Invalid id'}

@pytest.mark.parametrize('text, expected', [
('thiss is an exmple of spell chcking.',
'this is an example of spell checking.'),
Expand Down
Loading