From f07556039b5e25aa97e25538f9461b16b642c5a1 Mon Sep 17 00:00:00 2001 From: jprochazka Date: Fri, 19 Jul 2024 14:35:06 -0400 Subject: [PATCH] Completed tests for routes. --- build/portal/backend/backend/__init__.py | 2 +- .../portal/backend/backend/routes/aircraft.py | 18 ++- build/portal/backend/backend/routes/blog.py | 27 +++-- .../portal/backend/backend/routes/flights.py | 19 +++- build/portal/backend/backend/routes/links.py | 19 +++- .../backend/backend/routes/notifications.py | 23 ++-- .../portal/backend/backend/routes/settings.py | 18 ++- build/portal/backend/backend/routes/users.py | 27 +++-- .../portal/backend/backend/schemas/sqlite.sql | 2 +- .../static/adsb_receiver_api_v1_oas3.yaml | 28 ----- .../portal/backend/tests/test_routes_blog.py | 29 ++++- .../backend/tests/test_routes_flights.py | 105 +++++++++++++++++- .../portal/backend/tests/test_routes_links.py | 24 ++++ .../tests/test_routes_notifications.py | 8 ++ .../backend/tests/test_routes_settings.py | 14 ++- .../portal/backend/tests/test_routes_users.py | 31 ++++++ 16 files changed, 312 insertions(+), 82 deletions(-) diff --git a/build/portal/backend/backend/__init__.py b/build/portal/backend/backend/__init__.py index ffa0b7a..5a704c6 100644 --- a/build/portal/backend/backend/__init__.py +++ b/build/portal/backend/backend/__init__.py @@ -53,7 +53,7 @@ def create_app(test_config=None): scheduler.add_job(id = 'data_collection', func=data_collection_job, trigger="interval", seconds=15) scheduler.add_job(id = 'maintenance', func=maintenance_job, trigger="cron", hour=0) scheduler.init_app(app) - scheduler.start() + #scheduler.start() # /API/DOCS diff --git a/build/portal/backend/backend/routes/aircraft.py b/build/portal/backend/backend/routes/aircraft.py index 898cde7..fe4da26 100644 --- a/build/portal/backend/backend/routes/aircraft.py +++ b/build/portal/backend/backend/routes/aircraft.py @@ -2,6 +2,7 @@ import logging from flask import abort, Blueprint, jsonify, request from backend.db import get_db +from werkzeug.exceptions import HTTPException aircraft = Blueprint('aircraft', __name__) @@ -28,7 +29,9 @@ def get_aircraft_by_icao(icao): if not data: abort(404, description="Not Found") - return jsonify(data[0]), 200 + response = jsonify(data[0]) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 @aircraft.route('/api/aircraft//positions', methods=['GET']) def get_aircraft_positions(icao): @@ -47,7 +50,7 @@ def get_aircraft_positions(icao): #cursor.execute("SELECT COUNT(*) FROM aircraft WHERE icao = %s", (icao,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") cursor.execute("SELECT id FROM aircraft WHERE icao = ?", (icao,)) #cursor.execute("SELECT id FROM aircraft WHERE icao = %s", (icao,)) @@ -62,8 +65,11 @@ def get_aircraft_positions(icao): for result in result: positions.append(dict(zip(columns,result))) except Exception as ex: - logging.error(f"Error encountered while trying to get flight positions for aircraft ICAO {icao}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to get flight positions for aircraft ICAO {icao}", exc_info=ex) + abort(500, description="Internal Server Error") data={} data['offset'] = offset @@ -71,7 +77,9 @@ def get_aircraft_positions(icao): data['count'] = len(positions) data['positions'] = positions - return jsonify(data), 200 + response = jsonify(data) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 @aircraft.route('/api/aircraft', methods=['GET']) def get_aircraft(): diff --git a/build/portal/backend/backend/routes/blog.py b/build/portal/backend/backend/routes/blog.py index 7eb38ea..0caa8a7 100644 --- a/build/portal/backend/backend/routes/blog.py +++ b/build/portal/backend/backend/routes/blog.py @@ -1,10 +1,11 @@ +import datetime import logging -from datetime import datetime from flask import abort, Blueprint, jsonify, request from flask_jwt_extended import jwt_required from marshmallow import Schema, fields, ValidationError from backend.db import get_db +from werkzeug.exceptions import HTTPException blog = Blueprint('blog', __name__) @@ -28,6 +29,7 @@ def post_blog_post(): return jsonify(err.messages), 400 try: + now = str(datetime.datetime.now(datetime.UTC)) db=get_db() cursor=db.cursor() cursor.execute( @@ -35,7 +37,7 @@ def post_blog_post(): "INSERT INTO blog_posts (date, title, author, content) VALUES (?, ?, ?, ?)", #"INSERT INTO blog_posts (date, title, author, content) VALUES (%s, %s, %s, %s)", - (datetime.now(), payload['title'], payload['author'], payload['content']) + (now, payload['title'], payload['author'], payload['content']) ) db.commit() except Exception as ex: @@ -55,7 +57,7 @@ def delete_blog_post(blog_post_id): #cursor.execute("SELECT COUNT(*) FROM blog_posts WHERE id = %s", (blog_post_id,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: cursor.execute("DELETE FROM blog_posts WHERE id = ?", (blog_post_id,)) @@ -63,8 +65,11 @@ def delete_blog_post(blog_post_id): db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to delete blog post id {blog_post_id}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to delete blog post id {blog_post_id}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 @@ -110,19 +115,23 @@ def put_blog_post(blog_post_id): #cursor.execute("SELECT COUNT(*) FROM blog_posts WHERE id = %s", (blog_post_id,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: + now = str(datetime.datetime.now(datetime.UTC)) cursor.execute( "UPDATE blog_posts SET date = ?, title = ?, content = ? WHERE id = ?", #"UPDATE blog_posts SET date = %s, title = %s, content = %s WHERE id = %s", - (datetime.now(), payload['title'], payload['content'], blog_post_id) + (now, payload['title'], payload['content'], blog_post_id) ) db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to put blog post id {blog_post_id}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to put blog post id {blog_post_id}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 diff --git a/build/portal/backend/backend/routes/flights.py b/build/portal/backend/backend/routes/flights.py index 6139217..a4c90a7 100644 --- a/build/portal/backend/backend/routes/flights.py +++ b/build/portal/backend/backend/routes/flights.py @@ -1,8 +1,8 @@ import logging from flask import abort, Blueprint, jsonify, request -from flask_jwt_extended import jwt_required from backend.db import get_db +from werkzeug.exceptions import HTTPException flights = Blueprint('flights', __name__) @@ -29,7 +29,9 @@ def get_flight(flight): if not data: abort(404, description="Not Found") - return jsonify(data[0]), 200 + response = jsonify(data[0]) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 @flights.route('/api/flight//positions', methods=['GET']) def get_flight_positions(flight): @@ -48,7 +50,7 @@ def get_flight_positions(flight): #cursor.execute("SELECT COUNT(*) FROM flight WHERE flight = %s", (flight,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") cursor.execute("SELECT id FROM flights WHERE flight = ?", (flight,)) #cursor.execute("SELECT id FROM flights WHERE flight = %s", (flight,)) @@ -63,8 +65,11 @@ def get_flight_positions(flight): for result in result: positions.append(dict(zip(columns,result))) except Exception as ex: - logging.error(f"Error encountered while trying to get flight positions for flight {flight}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to get flight positions for flight {flight}", exc_info=ex) + abort(500, description="Internal Server Error") data={} data['offset'] = offset @@ -72,7 +77,9 @@ def get_flight_positions(flight): data['count'] = len(positions) data['positions'] = positions - return jsonify(data), 200 + response = jsonify(data) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 @flights.route('/api/flights', methods=['GET']) def get_flights(): diff --git a/build/portal/backend/backend/routes/links.py b/build/portal/backend/backend/routes/links.py index b53d500..537dcf1 100644 --- a/build/portal/backend/backend/routes/links.py +++ b/build/portal/backend/backend/routes/links.py @@ -4,6 +4,7 @@ from flask import abort, Blueprint, jsonify, request from flask_jwt_extended import jwt_required from marshmallow import Schema, fields, ValidationError from backend.db import get_db +from werkzeug.exceptions import HTTPException links = Blueprint('links', __name__) @@ -53,7 +54,7 @@ def delete_link(link_id): #cursor.execute("SELECT COUNT(*) FROM links WHERE id = %s", (link_id,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: cursor.execute("DELETE FROM links WHERE id = ?", (link_id,)) @@ -61,8 +62,11 @@ def delete_link(link_id): db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to delete link id {link_id}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to delete link id {link_id}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 @@ -107,7 +111,7 @@ def put_link(id): #cursor.execute("SELECT COUNT(*) FROM links WHERE id = %s", (id,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: cursor.execute( @@ -118,8 +122,11 @@ def put_link(id): ) db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to put link id {id}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to put link id {id}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 diff --git a/build/portal/backend/backend/routes/notifications.py b/build/portal/backend/backend/routes/notifications.py index de96a66..ca75b2c 100644 --- a/build/portal/backend/backend/routes/notifications.py +++ b/build/portal/backend/backend/routes/notifications.py @@ -3,6 +3,7 @@ import logging from flask import abort, Blueprint, jsonify, request from flask_jwt_extended import jwt_required from backend.db import get_db +from werkzeug.exceptions import HTTPException notifications = Blueprint('notifications', __name__) @@ -18,7 +19,7 @@ def delete_notification(flight): #cursor.execute("SELECT COUNT(*) FROM notifications WHERE flight = %s", (flight,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: cursor.execute("DELETE FROM notifications WHERE flight = ?", (flight,)) @@ -26,8 +27,11 @@ def delete_notification(flight): db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to delete blog post id {flight}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to delete blog post id {flight}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 @@ -42,7 +46,7 @@ def post_notification(flight): #cursor.execute("SELECT COUNT(*) FROM notifications WHERE flight = %s", (flight,)) if cursor.fetchone()[0] > 0: - return "Bad Request", 400 + abort(404, description="Not Found") else: cursor.execute( @@ -53,8 +57,11 @@ def post_notification(flight): ) db.commit() except Exception as ex: - logging.error('Error encountered while trying to add notification', exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error('Error encountered while trying to add notification', exc_info=ex) + abort(500, description="Internal Server Error") return "Created", 201 @@ -88,4 +95,6 @@ def get_notifications(): data['count'] = len(notifications) data['notifications'] = notifications - return jsonify(data), 200 \ No newline at end of file + response = jsonify(data) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 \ No newline at end of file diff --git a/build/portal/backend/backend/routes/settings.py b/build/portal/backend/backend/routes/settings.py index 8bdf140..81350a1 100644 --- a/build/portal/backend/backend/routes/settings.py +++ b/build/portal/backend/backend/routes/settings.py @@ -4,6 +4,7 @@ from flask import abort, Blueprint, jsonify, request from flask_jwt_extended import jwt_required from marshmallow import Schema, fields, ValidationError from backend.db import get_db +from werkzeug.exceptions import HTTPException settings = Blueprint('settings', __name__) @@ -29,7 +30,7 @@ def put_setting(): #cursor.execute("SELECT COUNT(*) FROM settings WHERE name = %s", (payload['name'],)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: cursor.execute( @@ -40,8 +41,11 @@ def put_setting(): ) db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to put setting named {payload['name']}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to put setting named {payload['name']}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 @@ -67,7 +71,9 @@ def get_setting(name): if not data: abort(404, description="Not Found") - return jsonify(data[0]), 200 + response = jsonify(data[0]) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 @settings.route('/api/settings', methods=['GET']) @jwt_required() @@ -86,5 +92,7 @@ def get_settings(): logging.error(f"Error encountered while trying to get settings", exc_info=ex) abort(500, description="Internal Server Error") - return jsonify(settings), 200 + response = jsonify(settings) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 diff --git a/build/portal/backend/backend/routes/users.py b/build/portal/backend/backend/routes/users.py index a3f54c8..7229083 100644 --- a/build/portal/backend/backend/routes/users.py +++ b/build/portal/backend/backend/routes/users.py @@ -4,6 +4,7 @@ from flask import abort, Blueprint, jsonify, request from flask_jwt_extended import jwt_required from marshmallow import Schema, fields, ValidationError from backend.db import get_db +from werkzeug.exceptions import HTTPException users = Blueprint('users', __name__) @@ -56,7 +57,7 @@ def delete_user(email): #cursor.execute("SELECT COUNT(*) FROM users WHERE email = %s", (email,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: cursor.execute("DELETE FROM users WHERE email = ?", (email,)) @@ -64,8 +65,11 @@ def delete_user(email): db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to delete user related to email {email}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to delete user related to email {email}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 @@ -92,7 +96,9 @@ def get_user(email): if not data: abort(404, description="Not Found") - return jsonify(data[0]), 200 + response = jsonify(data[0]) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 @users.route('/api/user/', methods=['PUT']) @jwt_required() @@ -110,7 +116,7 @@ def put_user(email): #cursor.execute("SELECT COUNT(*) FROM users WHERE email = %s", (email,)) if cursor.fetchone()[0] == 0: - return "Not Found", 404 + abort(404, description="Not Found") else: cursor.execute( @@ -121,8 +127,11 @@ def put_user(email): ) db.commit() except Exception as ex: - logging.error(f"Error encountered while trying to put user related to email {email}", exc_info=ex) - abort(500, description="Internal Server Error") + if isinstance(ex, HTTPException): + abort(ex.code) + else: + logging.error(f"Error encountered while trying to put user related to email {email}", exc_info=ex) + abort(500, description="Internal Server Error") return "No Content", 204 @@ -157,4 +166,6 @@ def get_users(): data['count'] = len(users) data['users'] = users - return jsonify(data), 200 \ No newline at end of file + response = jsonify(data) + response.headers.add('Access-Control-Allow-Origin', '*') + return response, 200 \ No newline at end of file diff --git a/build/portal/backend/backend/schemas/sqlite.sql b/build/portal/backend/backend/schemas/sqlite.sql index e580699..0cdfada 100644 --- a/build/portal/backend/backend/schemas/sqlite.sql +++ b/build/portal/backend/backend/schemas/sqlite.sql @@ -17,7 +17,7 @@ CREATE TABLE aircraft ( CREATE TABLE blog_posts ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT Not Null, - `date` TEXT NOT NULL, + `date` NUMERIC NOT NULL, `author` TEXT NOT NULL, `content` TEXT NOT NULL ); diff --git a/build/portal/backend/backend/static/adsb_receiver_api_v1_oas3.yaml b/build/portal/backend/backend/static/adsb_receiver_api_v1_oas3.yaml index e00fee5..777d51c 100644 --- a/build/portal/backend/backend/static/adsb_receiver_api_v1_oas3.yaml +++ b/build/portal/backend/backend/static/adsb_receiver_api_v1_oas3.yaml @@ -76,8 +76,6 @@ paths: type: object items: $ref: '#/components/schemas/Aircraft' - '401': - description: Unauthorized '404': description: Not Found '500': @@ -122,8 +120,6 @@ paths: type: object items: $ref: '#/components/schemas/GetAircraftPositionsResponse' - '401': - description: Unauthorized '400': description: Bad Request '500': @@ -162,8 +158,6 @@ paths: type: object items: $ref: '#/components/schemas/GetAircraftResponse' - '401': - description: Unauthorized '400': description: Bad Request '500': @@ -184,8 +178,6 @@ paths: type: object items: $ref: '#/components/schemas/GetAircraftCountResponse' - '401': - description: Unauthorized '500': description: Internal Server Error /blog/post: @@ -209,8 +201,6 @@ paths: description: Created '400': description: Bad Request - '401': - description: Unauthorized '500': description: Internal Server Error /blog/post/{id}: @@ -260,8 +250,6 @@ paths: type: object items: $ref: '#/components/schemas/BlogPost' - '401': - description: Unauthorized '404': description: Not Found '500': @@ -333,8 +321,6 @@ paths: type: object items: $ref: '#/components/schemas/GetBlogPostsResponse' - '401': - description: Unauthorized '400': description: Bad Request '500': @@ -362,8 +348,6 @@ paths: type: object items: $ref: '#/components/schemas/Flight' - '401': - description: Unauthorized '404': description: Not Found '500': @@ -408,8 +392,6 @@ paths: type: object items: $ref: '#/components/schemas/GetFlightPositionsResponse' - '401': - description: Unauthorized '400': description: Bad Request '500': @@ -448,8 +430,6 @@ paths: type: object items: $ref: '#/components/schemas/GetFlightsResponse' - '401': - description: Unauthorized '400': description: Bad Request '500': @@ -470,8 +450,6 @@ paths: type: object items: $ref: '#/components/schemas/GetFlightsCountResponse' - '401': - description: Unauthorized '500': description: Internal Server Error /link: @@ -621,8 +599,6 @@ paths: type: object items: $ref: '#/components/schemas/GetLinksResponse' - '401': - description: Unauthorized '400': description: Bad Request '500': @@ -709,8 +685,6 @@ paths: $ref: '#/components/schemas/GetNotificationsResponse' '400': description: Bad Request - '401': - description: Unauthorized '500': description: Internal Server Error /setting: @@ -763,8 +737,6 @@ paths: type: object items: $ref: '#/components/schemas/Setting' - '401': - description: Unauthorized '404': description: Not Found '500': diff --git a/build/portal/backend/tests/test_routes_blog.py b/build/portal/backend/tests/test_routes_blog.py index 80ec7cb..5c6afa6 100644 --- a/build/portal/backend/tests/test_routes_blog.py +++ b/build/portal/backend/tests/test_routes_blog.py @@ -16,6 +16,15 @@ def test_post_blog_post_200(client, app): response = client.post('/api/blog/post', headers=request_headers, json=request_json) assert response.status_code == 201 +def test_post_blog_post_401(client): + request_json = { + 'title': 'Title Five', + 'author': 'User Two', + 'content': 'Content for blog post five.' + } + response = client.post('/api/blog/post', json=request_json) + assert response.status_code == 401 + def test_post_blog_post_400_missing_title(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -66,6 +75,10 @@ def test_delete_blog_post_204(client, app): response = client.delete('/api/blog/post/2', headers=request_headers) assert response.status_code == 204 +def test_delete_blog_post_401(client): + response = client.delete('/api/blog/post/2') + assert response.status_code == 401 + def test_delete_blog_post_404(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -92,7 +105,7 @@ def test_get_blog_post_404(client): # PUT /blog/post/{id} -def test_put_user_204(client, app): +def test_put_blog_post_204(client, app): with app.app_context(): access_token = create_access_token(identity="developer") request_headers = { @@ -105,7 +118,15 @@ def test_put_user_204(client, app): response = client.put('/api/blog/post/1', headers=request_headers, json=request_json) assert response.status_code == 204 -def test_put_user_400_missing_title(client, app): +def test_put_blog_post_401(client): + request_json = { + 'title': 'Updated Title One', + 'content': 'Updated content for blog post one.' + } + response = client.put('/api/blog/post/1', json=request_json) + assert response.status_code == 401 + +def test_put_blog_post_400_missing_title(client, app): with app.app_context(): access_token = create_access_token(identity="developer") request_headers = { @@ -117,7 +138,7 @@ def test_put_user_400_missing_title(client, app): response = client.put('/api/blog/post/1', headers=request_headers, json=request_json) assert response.status_code == 400 -def test_put_user_400_missing_content(client, app): +def test_put_blog_post_400_missing_content(client, app): with app.app_context(): access_token = create_access_token(identity="developer") request_headers = { @@ -129,7 +150,7 @@ def test_put_user_400_missing_content(client, app): response = client.put('/api/blog/post/1', headers=request_headers, json=request_json) assert response.status_code == 400 -def test_put_user_404(client, app): +def test_put_blog_post_404(client, app): with app.app_context(): access_token = create_access_token(identity="developer") request_headers = { diff --git a/build/portal/backend/tests/test_routes_flights.py b/build/portal/backend/tests/test_routes_flights.py index 23424bb..21698c6 100644 --- a/build/portal/backend/tests/test_routes_flights.py +++ b/build/portal/backend/tests/test_routes_flights.py @@ -67,4 +67,107 @@ def test_get_flight_positions_200(client): assert response.json['positions'][3]['track'] == 91 assert response.json['positions'][3]['altitude'] == 37225 assert response.json['positions'][3]['verticle_rate'] == 1216 - assert response.json['positions'][3]['speed'] == 484 \ No newline at end of file + assert response.json['positions'][3]['speed'] == 484 + +def test_get_flight_404(client): + response = client.get('/api/flight/FLT0000/positions') + assert response.status_code == 404 + +# GET /api/flights + +def test_get_flights_200(client): + response = client.get('/api/flights') + assert response.status_code == 200 + assert response.json['offset'] == 0 + assert response.json['limit'] == 50 + assert response.json['count'] == 4 + assert response.json['flights'][0]['id'] == 4 + assert response.json['flights'][0]['aircraft'] == 5 + assert response.json['flights'][0]['flight'] == "FLT0005" + assert response.json['flights'][0]['first_seen'] == "2024-07-17 04:40:44" + assert response.json['flights'][0]['last_seen'] == "2024-06-17 04:44:04" + assert response.json['flights'][1]['id'] == 3 + assert response.json['flights'][1]['aircraft'] == 3 + assert response.json['flights'][1]['flight'] == "FLT0003" + assert response.json['flights'][1]['first_seen'] == "2024-07-17 03:30:33" + assert response.json['flights'][1]['last_seen'] == "2024-06-17 03:33:03" + assert response.json['flights'][2]['id'] == 2 + assert response.json['flights'][2]['aircraft'] == 2 + assert response.json['flights'][2]['flight'] == "FLT0002" + assert response.json['flights'][2]['first_seen'] == "2024-07-17 02:20:22" + assert response.json['flights'][2]['last_seen'] == "2024-06-17 02:22:02" + assert response.json['flights'][3]['id'] == 1 + assert response.json['flights'][3]['aircraft'] == 1 + assert response.json['flights'][3]['flight'] == "FLT0001" + assert response.json['flights'][3]['first_seen'] == "2024-07-17 01:10:11" + assert response.json['flights'][3]['last_seen'] == "2024-06-17 01:11:01" + +def test_get_flights_200_offset(client): + response = client.get('/api/flights?offset=2') + assert response.status_code == 200 + assert response.json['offset'] == 2 + assert response.json['limit'] == 50 + assert response.json['count'] == 2 + assert response.json['flights'][0]['id'] == 2 + assert response.json['flights'][0]['aircraft'] == 2 + assert response.json['flights'][0]['flight'] == "FLT0002" + assert response.json['flights'][0]['first_seen'] == "2024-07-17 02:20:22" + assert response.json['flights'][0]['last_seen'] == "2024-06-17 02:22:02" + assert response.json['flights'][1]['id'] == 1 + assert response.json['flights'][1]['aircraft'] == 1 + assert response.json['flights'][1]['flight'] == "FLT0001" + assert response.json['flights'][1]['first_seen'] == "2024-07-17 01:10:11" + assert response.json['flights'][1]['last_seen'] == "2024-06-17 01:11:01" + +def test_get_flights_200_limit(client): + response = client.get('/api/flights?limit=2') + assert response.status_code == 200 + assert response.json['offset'] == 0 + assert response.json['limit'] == 2 + assert response.json['count'] == 2 + assert response.json['flights'][0]['id'] == 4 + assert response.json['flights'][0]['aircraft'] == 5 + assert response.json['flights'][0]['flight'] == "FLT0005" + assert response.json['flights'][0]['first_seen'] == "2024-07-17 04:40:44" + assert response.json['flights'][0]['last_seen'] == "2024-06-17 04:44:04" + assert response.json['flights'][1]['id'] == 3 + assert response.json['flights'][1]['aircraft'] == 3 + assert response.json['flights'][1]['flight'] == "FLT0003" + assert response.json['flights'][1]['first_seen'] == "2024-07-17 03:30:33" + assert response.json['flights'][1]['last_seen'] == "2024-06-17 03:33:03" + +def test_get_flights_200_offset_and_limit(client): + response = client.get('/api/flights?offset=1&limit=2') + assert response.status_code == 200 + assert response.json['offset'] == 1 + assert response.json['limit'] == 2 + assert response.json['count'] == 2 + assert response.json['flights'][0]['id'] == 3 + assert response.json['flights'][0]['aircraft'] == 3 + assert response.json['flights'][0]['flight'] == "FLT0003" + assert response.json['flights'][0]['first_seen'] == "2024-07-17 03:30:33" + assert response.json['flights'][0]['last_seen'] == "2024-06-17 03:33:03" + assert response.json['flights'][1]['id'] == 2 + assert response.json['flights'][1]['aircraft'] == 2 + assert response.json['flights'][1]['flight'] == "FLT0002" + assert response.json['flights'][1]['first_seen'] == "2024-07-17 02:20:22" + assert response.json['flights'][1]['last_seen'] == "2024-06-17 02:22:02" + +def test_get_flights_400_offset_less_than_0(client): + response = client.get('/api/flights?offset=-1') + assert response.status_code == 400 + +def test_get_flights_400_limit_less_than_0(client): + response = client.get('/api/flights?limit=-1') + assert response.status_code == 400 + +def test_get_flights_400_limit_greater_than_100(client): + response = client.get('/api/flights?limit=101') + assert response.status_code == 400 + +# GET /api/flights/count + +def test_get_flights_count(client): + response = client.get('/api/flights/count') + assert response.status_code == 200 + assert response.json["flights"] == 4 \ No newline at end of file diff --git a/build/portal/backend/tests/test_routes_links.py b/build/portal/backend/tests/test_routes_links.py index a3598e5..a00a5b1 100644 --- a/build/portal/backend/tests/test_routes_links.py +++ b/build/portal/backend/tests/test_routes_links.py @@ -15,6 +15,14 @@ def test_post_link_200(client, app): response = client.post('/api/link', headers=request_headers, json=request_json) assert response.status_code == 201 +def test_post_link_401(client): + request_json = { + 'name': 'Link Four', + 'address': 'https://adsbportal.com/four' + } + response = client.post('/api/link', json=request_json) + assert response.status_code == 401 + def test_post_link_400_missing_name(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -50,6 +58,10 @@ def test_delete_link_204(client, app): response = client.delete('/api/link/1', headers=request_headers) assert response.status_code == 204 +def test_delete_link_401(client): + response = client.delete('/api/link/1') + assert response.status_code == 401 + def test_delete_link_404(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -72,6 +84,10 @@ def test_get_link_200(client, app): assert response.json['id'] == 2 assert response.json['address'] == "https://adsbportal.com/two" +def test_get_link_401(client, app): + response = client.get('/api/link/2') + assert response.status_code == 401 + def test_get_user_404(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -96,6 +112,14 @@ def test_put_link_204(client, app): response = client.put('/api/link/3', headers=request_headers, json=request_json) assert response.status_code == 204 +def test_put_link_401(client): + request_json = { + 'name': 'Link Three Updated', + 'address': 'https://adsbportal.com/three-updated' + } + response = client.put('/api/link/3', json=request_json) + assert response.status_code == 401 + def test_put_link_400_missing_name(client, app): with app.app_context(): access_token = create_access_token(identity="developer") diff --git a/build/portal/backend/tests/test_routes_notifications.py b/build/portal/backend/tests/test_routes_notifications.py index 4852fcf..9cd312e 100644 --- a/build/portal/backend/tests/test_routes_notifications.py +++ b/build/portal/backend/tests/test_routes_notifications.py @@ -11,6 +11,10 @@ def test_delete_notification_204(client, app): response = client.delete('/api/notification/FLT0013', headers=request_headers) assert response.status_code == 204 +def test_delete_notification_401(client): + response = client.delete('/api/notification/FLT0013') + assert response.status_code == 401 + def test_delete_notification_404(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -31,6 +35,10 @@ def test_post_notification_200(client, app): response = client.post('/api/notification/FLT0014', headers=request_headers) assert response.status_code == 201 +def test_post_notification_401(client): + response = client.post('/api/notification/FLT0014') + assert response.status_code == 401 + # GET /notifications def test_get_notifications_200(client): diff --git a/build/portal/backend/tests/test_routes_settings.py b/build/portal/backend/tests/test_routes_settings.py index 15d6d1d..58eb9fc 100644 --- a/build/portal/backend/tests/test_routes_settings.py +++ b/build/portal/backend/tests/test_routes_settings.py @@ -15,6 +15,14 @@ def test_put_setting_204(client, app): response = client.put('/api/setting', headers=request_headers, json=request_json) assert response.status_code == 204 +def test_put_setting_401(client): + request_json = { + 'name': 'setting_three', + 'value': 'Updated Setting Three' + } + response = client.put('/api/setting', json=request_json) + assert response.status_code == 401 + def test_put_setting_400_missing_name(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -84,4 +92,8 @@ def test_get_settings_200(client, app): assert response.json[1]['value'] == "Value Three" assert response.json[2]['id'] == 2 assert response.json[2]['name'] == "setting_two" - assert response.json[2]['value'] == "Value Two" \ No newline at end of file + assert response.json[2]['value'] == "Value Two" + +def test_get_settings_401(client): + response = client.get('/api/settings') + assert response.status_code == 401 \ No newline at end of file diff --git a/build/portal/backend/tests/test_routes_users.py b/build/portal/backend/tests/test_routes_users.py index 65ca40f..253875a 100644 --- a/build/portal/backend/tests/test_routes_users.py +++ b/build/portal/backend/tests/test_routes_users.py @@ -17,6 +17,16 @@ def test_post_user_200(client, app): response = client.post('/api/user', headers=request_headers, json=request_json) assert response.status_code == 201 +def test_post_user_401(client): + request_json = { + 'name': 'Name Four', + 'email': 'noreply@email-four.com', + 'password': '$2y$LFLCJxrho1eGVPp9p9ygc5fuK1XWzLWS6nsWVJvJNbtZOeMVkuBJzTXG', + 'administrator': False + } + response = client.post('/api/user', json=request_json) + assert response.status_code == 401 + def test_post_user_200_as_administrator(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -99,6 +109,10 @@ def test_delete_user_204(client, app): response = client.delete('/api/user/noreply@email-three.com', headers=request_headers) assert response.status_code == 204 +def test_delete_user_401(client): + response = client.delete('/api/user/noreply@email-three.com') + assert response.status_code == 401 + def test_delete_user_404(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -124,6 +138,10 @@ def test_get_user_200(client, app): assert response.json['password'] == "$2y$0htWdxS7PxTvIwJNo2COJ7Rywgif4En0TmJbDvrjLRfWZOBX526yJUKW" assert response.json['administrator'] == 1 +def test_get_user_401(client): + response = client.get('/api/user/noreply@email-one.com') + assert response.status_code == 401 + def test_get_user_404(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -149,6 +167,15 @@ def test_put_user_204(client, app): response = client.put('/api/user/noreply@email-two.com', headers=request_headers, json=request_json) assert response.status_code == 204 +def test_put_user_401(client): + request_json = { + 'name': 'Name Two', + 'password': '$2y$VxTtlJcPlXFj3eHzZTAvGKHXVyHWqK12TXXdUT9SHaAXKC6l7spI7sqv', + 'administrator': 1 + } + response = client.put('/api/user/noreply@email-two.com', json=request_json) + assert response.status_code == 401 + def test_put_user_400_missing_name(client, app): with app.app_context(): access_token = create_access_token(identity="developer") @@ -232,6 +259,10 @@ def test_get_users_200(client, app): assert response.json['users'][2]['password'] == "$2y$ui7QK047JldTekx828J2rfSVQ7N5yo6ETQIYGoBqpfFRbNr3EvWzQzt6" assert response.json['users'][2]['administrator'] == 0 +def test_get_users_401(client): + response = client.get('/api/users') + assert response.status_code == 401 + def test_get_users_200_offset(client, app): with app.app_context(): access_token = create_access_token(identity="developer")