mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-06 00:28:25 -04:00
Doing some additional cleaning up of things, getting the project's
testing really in place. Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
@@ -114,43 +114,6 @@ def activate_virtualenv_in_precommit_hooks(session: Session) -> None:
|
||||
break
|
||||
|
||||
|
||||
@session(name="pre-commit", python=python_versions[0])
|
||||
def precommit(session: Session) -> None:
|
||||
"""Lint using pre-commit.
|
||||
|
||||
Args:
|
||||
session: The Nox session object.
|
||||
"""
|
||||
args = session.posargs or [
|
||||
"run",
|
||||
"--all-files",
|
||||
"--hook-stage=manual",
|
||||
"--show-diff-on-failure",
|
||||
]
|
||||
session.install(
|
||||
"black",
|
||||
"darglint",
|
||||
"flake8",
|
||||
"flake8-bandit",
|
||||
"flake8-bugbear",
|
||||
"flake8-docstrings",
|
||||
"flake8-rst-docstrings",
|
||||
"isort",
|
||||
"pep8-naming",
|
||||
"pre-commit",
|
||||
"pre-commit-hooks",
|
||||
"pyupgrade",
|
||||
)
|
||||
session.run("pre-commit", *args)
|
||||
# Run frontend lint using yarn lint
|
||||
import os
|
||||
|
||||
os.chdir("../frontend")
|
||||
session.run("yarn", "lint", external=True)
|
||||
if args and args[0] == "install":
|
||||
activate_virtualenv_in_precommit_hooks(session)
|
||||
|
||||
|
||||
@session(python=python_versions[0])
|
||||
def safety(session: Session) -> None:
|
||||
"""Scan dependencies for insecure packages.
|
||||
|
||||
@@ -70,6 +70,18 @@ async def get_booking(session: AsyncSession, booking_id: int) -> Booking:
|
||||
|
||||
|
||||
async def _validate_new_booking_room_exists(session: AsyncSession, room_id: int) -> Any:
|
||||
"""Validate that the room exists for a new booking.
|
||||
|
||||
Args:
|
||||
session (AsyncSession): Database session.
|
||||
room_id (int): ID of the room to validate.
|
||||
|
||||
Returns:
|
||||
Any: The room object if it exists.
|
||||
|
||||
Raises:
|
||||
ValueError: If the room does not exist.
|
||||
"""
|
||||
try:
|
||||
return await get_room(session, room_id)
|
||||
except Exception as e:
|
||||
@@ -80,6 +92,16 @@ async def _validate_new_booking_room_exists(session: AsyncSession, room_id: int)
|
||||
def _validate_new_booking_time_constraints(
|
||||
start: datetime, end: datetime, now: datetime
|
||||
) -> None:
|
||||
"""Validate booking time constraints for a new booking.
|
||||
|
||||
Args:
|
||||
start (datetime): Start time of the booking.
|
||||
end (datetime): End time of the booking.
|
||||
now (datetime): Current time.
|
||||
|
||||
Raises:
|
||||
ValueError: If booking is in the past or start >= end.
|
||||
"""
|
||||
if start < now or end < now:
|
||||
logger.warning("Attempted to create booking in the past.")
|
||||
raise ValueError("Bookings cannot be made in the past.")
|
||||
@@ -91,6 +113,17 @@ def _validate_new_booking_time_constraints(
|
||||
def _validate_new_booking_max_future(
|
||||
start: datetime, end: datetime, now: datetime, max_months: int
|
||||
) -> None:
|
||||
"""Validate that booking is not too far in the future.
|
||||
|
||||
Args:
|
||||
start (datetime): Start time of the booking.
|
||||
end (datetime): End time of the booking.
|
||||
now (datetime): Current time.
|
||||
max_months (int): Maximum months allowed in advance.
|
||||
|
||||
Raises:
|
||||
ValueError: If booking is too far in the future.
|
||||
"""
|
||||
max_future = now + timedelta(days=30 * max_months)
|
||||
if start > max_future or end > max_future:
|
||||
logger.warning("Attempted to create booking too far in the future.")
|
||||
@@ -102,6 +135,15 @@ def _validate_new_booking_max_future(
|
||||
async def _validate_new_booking_no_overlap(
|
||||
session: AsyncSession, booking: Booking
|
||||
) -> None:
|
||||
"""Validate that the new booking does not overlap with existing bookings.
|
||||
|
||||
Args:
|
||||
session (AsyncSession): Database session.
|
||||
booking (Booking): Booking object to validate.
|
||||
|
||||
Raises:
|
||||
ValueError: If booking times overlap with an existing booking.
|
||||
"""
|
||||
overlap_stmt = select(Booking).where(
|
||||
Booking.room_id == booking.room_id,
|
||||
func.tstzrange(Booking.start_time, Booking.end_time, "[)").op("&&")(
|
||||
@@ -195,6 +237,19 @@ async def _validate_room_exists(
|
||||
room_id: int,
|
||||
get_room: Callable[[AsyncSession, int], Awaitable[Any]],
|
||||
) -> Any:
|
||||
"""Validate that the room exists for an update.
|
||||
|
||||
Args:
|
||||
session (AsyncSession): Database session.
|
||||
room_id (int): ID of the room to validate.
|
||||
get_room (Callable): Function to get the room.
|
||||
|
||||
Returns:
|
||||
Any: The room object if it exists.
|
||||
|
||||
Raises:
|
||||
ValueError: If the room does not exist.
|
||||
"""
|
||||
try:
|
||||
return await get_room(session, room_id)
|
||||
except Exception as e:
|
||||
@@ -208,6 +263,17 @@ def _validate_time_constraints(
|
||||
now: datetime,
|
||||
max_months: int,
|
||||
) -> None:
|
||||
"""Validate booking time constraints for an update.
|
||||
|
||||
Args:
|
||||
new_start (datetime): New start time.
|
||||
new_end (datetime): New end time.
|
||||
now (datetime): Current time.
|
||||
max_months (int): Maximum months allowed in advance.
|
||||
|
||||
Raises:
|
||||
ValueError: If booking is in the past, start >= end, or too far in the future.
|
||||
"""
|
||||
if new_start < now or new_end < now:
|
||||
logger.warning("Attempted to update booking to be in the past.")
|
||||
raise ValueError("Bookings cannot be made in the past.")
|
||||
@@ -229,6 +295,18 @@ async def _validate_no_overlap(
|
||||
new_start: datetime,
|
||||
new_end: datetime,
|
||||
) -> None:
|
||||
"""Validate that the updated booking does not overlap with existing bookings.
|
||||
|
||||
Args:
|
||||
session (AsyncSession): Database session.
|
||||
booking_id (int): ID of the booking to update.
|
||||
room_id (int): Room ID.
|
||||
new_start (datetime): New start time.
|
||||
new_end (datetime): New end time.
|
||||
|
||||
Raises:
|
||||
ValueError: If booking times overlap with an existing booking.
|
||||
"""
|
||||
overlap_stmt = select(Booking).where(
|
||||
Booking.room_id == room_id,
|
||||
Booking.id != booking_id,
|
||||
|
||||
15
frontend/.storybook/main.js
Normal file
15
frontend/.storybook/main.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-interactions",
|
||||
],
|
||||
framework: {
|
||||
name: "@storybook/react-webpack5",
|
||||
options: {},
|
||||
},
|
||||
docs: {
|
||||
autodocs: true,
|
||||
},
|
||||
};
|
||||
@@ -9,6 +9,54 @@ from pathlib import Path
|
||||
import nox
|
||||
|
||||
|
||||
@nox.session(name="typecheck")
|
||||
def typecheck(session: nox.Session) -> None:
|
||||
"""Run TypeScript type checks.
|
||||
|
||||
Args:
|
||||
session: The Nox session object.
|
||||
"""
|
||||
frontend_dir = Path(__file__).parent
|
||||
os.chdir(frontend_dir)
|
||||
session.run("yarn", "tsc", "--noEmit", external=True)
|
||||
|
||||
|
||||
@nox.session(name="coverage")
|
||||
def coverage(session: nox.Session) -> None:
|
||||
"""Run Jest with coverage reporting.
|
||||
|
||||
Args:
|
||||
session: The Nox session object.
|
||||
"""
|
||||
frontend_dir = Path(__file__).parent
|
||||
os.chdir(frontend_dir)
|
||||
session.run("yarn", "jest", "--coverage", external=True)
|
||||
|
||||
|
||||
@nox.session(name="audit")
|
||||
def audit(session: nox.Session) -> None:
|
||||
"""Run yarn audit for security checks.
|
||||
|
||||
Args:
|
||||
session: The Nox session object.
|
||||
"""
|
||||
frontend_dir = Path(__file__).parent
|
||||
os.chdir(frontend_dir)
|
||||
session.run("yarn", "audit", external=True)
|
||||
|
||||
|
||||
@nox.session(name="storybook")
|
||||
def storybook(session: nox.Session) -> None:
|
||||
"""Run Storybook for frontend documentation.
|
||||
|
||||
Args:
|
||||
session: The Nox session object.
|
||||
"""
|
||||
frontend_dir = Path(__file__).parent
|
||||
os.chdir(frontend_dir)
|
||||
session.run("yarn", "storybook", external=True)
|
||||
|
||||
|
||||
@nox.session(name="jest")
|
||||
def jest(session: nox.Session) -> None:
|
||||
"""Run frontend Jest tests using yarn.
|
||||
|
||||
@@ -62,6 +62,10 @@
|
||||
"@babel/preset-env": "^7.28.3",
|
||||
"@babel/preset-react": "^7.27.1",
|
||||
"@babel/preset-typescript": "^7.27.1",
|
||||
"@storybook/addon-essentials": "^8.6.14",
|
||||
"@storybook/addon-interactions": "^8.6.14",
|
||||
"@storybook/addon-links": "^9.1.7",
|
||||
"@storybook/react-webpack5": "^9.1.7",
|
||||
"@types/testing-library__user-event": "^4.2.0",
|
||||
"babel-jest": "^30.1.2",
|
||||
"jest": "^30.1.1",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
43
noxfile.py
43
noxfile.py
@@ -3,7 +3,46 @@
|
||||
Run with `nox -s <session>` from the project root.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import nox
|
||||
from nox_poetry import Session
|
||||
|
||||
|
||||
python_versions = ["3.13"]
|
||||
|
||||
|
||||
@nox.session(name="pre-commit", python=python_versions[0])
|
||||
def precommit(session: Session) -> None:
|
||||
"""Lint using pre-commit for the whole project.
|
||||
|
||||
Args:
|
||||
session: The Nox session object.
|
||||
"""
|
||||
args = session.posargs or [
|
||||
"run",
|
||||
"--all-files",
|
||||
"--hook-stage=manual",
|
||||
"--show-diff-on-failure",
|
||||
]
|
||||
session.install(
|
||||
"black",
|
||||
"darglint",
|
||||
"flake8",
|
||||
"flake8-bandit",
|
||||
"flake8-bugbear",
|
||||
"flake8-docstrings",
|
||||
"flake8-rst-docstrings",
|
||||
"isort",
|
||||
"pep8-naming",
|
||||
"pre-commit",
|
||||
"pre-commit-hooks",
|
||||
"pyupgrade",
|
||||
)
|
||||
session.run("pre-commit", *args)
|
||||
# Run frontend lint using yarn lint
|
||||
os.chdir("frontend")
|
||||
session.run("yarn", "lint", external=True)
|
||||
|
||||
|
||||
backend_sessions = [
|
||||
@@ -20,6 +59,10 @@ backend_sessions = [
|
||||
|
||||
frontend_sessions = [
|
||||
"jest",
|
||||
"typecheck",
|
||||
"coverage",
|
||||
"audit",
|
||||
"storybook",
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user