diff --git a/.gitignore b/.gitignore index cdb93cd5..69ad2946 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .python-version +__pycache__/ diff --git a/README.md b/README.md index 6990ecb6..58bf5381 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ This is a full-stack application simulating an online booking system for confere - Pytest, coverage, pre-commit hooks, and code style enforcement for backend - Jest and React Testing Library, code style enforcement and additional pre-commit hooks for frontend +- All tests can be run from the`nox` command in the root directory ### Docker Compose for Orchestration @@ -186,15 +187,29 @@ nox --session=tests ```bash cd frontend -yarn run jest +nox +# or run only nox tests: +nox --session=jest ``` +#### All tests + +from the project root + +```bash +nox +``` + +Note - you can use any of the sessions from frontend or backend here to isolate just that test. + #### Further improvements Integration testing, and end-to-end tests really would make this robust. Having all of the tests run in CICD before allowing code to be merged/commited to the main branch would be a mechanism to help ensure code quality. I would have set up the github project to have "feature branches" be made, to add whatever feature that a work item/issue had, and then Peer Reviews - typically set up with 2 peers reviewing 1 PR and approving it, aswell as all CICD checks/tests needing to pass before allowing the branch to be merged. I would have templates in place for creating a PR, with a set of instructions that would give the "definition of done" - a checklist that would need to be completed before the issue could be marked as completed and a PR could then be reviewed. +Further kinds of tests can be added for the frontend through the frontend's noxfile. + ## Diagrams ### Docker Compose Components diff --git a/backend/noxfile.py b/backend/noxfile.py index 15b70107..7cb22f17 100644 --- a/backend/noxfile.py +++ b/backend/noxfile.py @@ -142,6 +142,8 @@ def precommit(session: Session) -> None: "pyupgrade", ) session.run("pre-commit", *args) + # Run frontend lint using yarn lint + session.run("yarn", "lint", external=True) if args and args[0] == "install": activate_virtualenv_in_precommit_hooks(session) diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json new file mode 100644 index 00000000..ebb429a5 --- /dev/null +++ b/frontend/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "extends": [ + "react-app", + "react-app/jest", + "plugin:@typescript-eslint/recommended" + ] +} diff --git a/frontend/noxfile.py b/frontend/noxfile.py new file mode 100644 index 00000000..e6e32bb0 --- /dev/null +++ b/frontend/noxfile.py @@ -0,0 +1,21 @@ +"""Nox sessions for frontend tasks. + +Run with `nox -s ` from the project root or frontend directory. +""" + +import os +from pathlib import Path + +import nox + + +@nox.session(name="jest") +def jest(session: nox.Session) -> None: + """Run frontend Jest tests using yarn. + + Args: + session: The Nox session object. + """ + frontend_dir = Path(__file__).parent + os.chdir(frontend_dir) + session.run("yarn", "run", "jest", external=True) diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 00000000..412beaf1 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,73 @@ +"""Root noxfile for orchestrating backend and frontend tasks. + +Run with `nox -s ` from the project root. +""" + +import nox + + +backend_sessions = [ + "pre-commit", + "safety", + "mypy", + "tests", + "coverage", + "typeguard", + "xdoctest", + "docs-build", + "docs", +] + +frontend_sessions = [ + "jest", +] + + +def _delegate(session: nox.Session, subdir: str, session_name: str) -> None: # type: ignore + """Delegate session execution to a subdirectory noxfile. + + Args: + session: The Nox session object. + subdir: Subdirectory containing the noxfile. + session_name: Name of the session to run. + """ + session.run( + "nox", + "-f", + f"{subdir}/noxfile.py", + "-s", + session_name, + *session.posargs, + external=True, + ) + + +for name in backend_sessions: + func_name = name.replace("-", "_") + exec( + f''' +@nox.session(name={name!r}) +def {func_name}_delegator(session: nox.Session) -> None: + """Delegates to backend/{name} session. + + Args: + session: The Nox session object. + """ + _delegate(session, 'backend', {name!r}) +''' + ) + +for name in frontend_sessions: + func_name = name.replace("-", "_") + exec( + f''' +@nox.session(name={name!r}) +def {func_name}_delegator(session: nox.Session) -> None: + """Delegates to frontend/{name} session. + + Args: + session: The Nox session object. + """ + _delegate(session, 'frontend', {name!r}) +''' + )