Skip to content

Commit e30f56f

Browse files
Add db seeding script for jwt protected route testing (#12)
* Moved script tests to tests/scripts/. * Refactored test_create_books.py to use with blocks for mocks, fixing a mock leak that caused KeyError in other tests. * Removed runpy test and helper to resolve mock leak. * Added TDD failing test for seed_users() and supporting files: - scripts/test_data/sample_user_data.json - scripts/seed_user.py * Added skip-if-existing-user logic to seed_users(). * Implemented seed_users(); all TDD tests now pass.\ * Added tests for main() covering happy path and failure modes → 100% coverage. * Refactored script execution into main(); fixed pylint issues. * Updated script to use absolute path based on script location. * Updated Makefile with seed-users command. * Updated README.md to document seed_users(). Co-authored-by: Copilot <[email protected]>
1 parent 7df5893 commit e30f56f

File tree

7 files changed

+374
-138
lines changed

7 files changed

+374
-138
lines changed

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ PIP = $(VENV_DIR)/bin/pip
1010
.DEFAULT_GOAL := help
1111

1212
# Phony Targets
13-
.PHONY: run clean test help lint db-seed db-clean db-setup
13+
.PHONY: run clean test help lint db-seed db-clean db-setup seed-users
1414

1515
# ==============================================================================
1616
# CORE COMMANDS - For everyday development
@@ -30,6 +30,7 @@ help: ## Show help
3030
@echo " make db-setup Reset the database to a clean, seeded state. (Runs db-clean then db-seed)"
3131
@echo " make db-seed Populate the database with initial data."
3232
@echo " make db-clean Delete all book data from the database."
33+
@echo " make seed-users Populate the database with initial user data."
3334

3435
install: $(PIP)
3536

@@ -86,3 +87,8 @@ db-seed: install
8687
db-clean: install
8788
@echo "--> ⚠️ Deleting all books from the database..."
8889
PATH=$(VENV_DIR)/bin:$$PATH PYTHONPATH=. $(PYTHON) -m scripts.delete_books
90+
91+
92+
seed-users: install
93+
@echo "--- Seeding the database with user data ---"
94+
PATH=$(VENV_DIR)/bin:$$PATH PYTHONPATH=. $(PYTHON) -m scripts.seed_users

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ To use the API, you first need to populate the database with some initial data.
8080
| Command | Description |
8181
|----------------|-----------------------------------------------------------------------------|
8282
| `make db-setup`| **(Recommended)** Resets the database. Runs `db-clean` and then `db-seed`. |
83-
| `make db-seed` | Populates the database with the contents of `scripts/books.json`. |
83+
| `make db-seed` | Populates the database with the contents of `scripts/test_data/books.json`. |
8484
| `make db-clean`| Deletes all documents from the 'books' collection. Useful for starting fresh. |
85+
| `make seed-users`| *** THIS IS WIP right now: The user data is required for the JWT authentication system. *** Populates the database with initial user data for authentication from `scripts/test_data/sample_user_data.json`. |
8586

8687
To perform a full database reset, run:
8788
```bash

scripts/seed_users.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""Seeding user_data script"""
2+
3+
import os
4+
import json
5+
6+
import bcrypt
7+
8+
from app import create_app
9+
from app.extensions import mongo
10+
11+
12+
def seed_users(users_to_seed: list) -> str:
13+
"""
14+
Processes a list of user data, hashes their passwords,
15+
and inserts them into the database. Skips existing users.
16+
17+
This function MUST be run within an active Flask application context.
18+
19+
Args:
20+
users_to_seed: A list of dicts, each with 'email' and 'password'.
21+
22+
Returns:
23+
A string summarizing the result.
24+
"""
25+
count = 0
26+
27+
for user_data in users_to_seed:
28+
email = user_data["email"]
29+
30+
# Check if data already exists
31+
if mongo.db.users.find_one({"email": email}):
32+
print(f"Skipping existing user: {email}")
33+
continue
34+
35+
# hash the password
36+
hashed_password = bcrypt.hashpw(
37+
user_data["password"].encode("utf-8"), bcrypt.gensalt()
38+
)
39+
40+
# insert to new user
41+
mongo.db.users.insert_one(
42+
{"email": email, "password_hash": hashed_password.decode("utf-8")}
43+
)
44+
count += 1
45+
print(f"Created user: {email}")
46+
47+
return f"Successfully seeded {count} users"
48+
49+
50+
def main():
51+
"""
52+
Main execution function to run the seeding process.
53+
handles app context, data loading, and calls the core seeding logic.
54+
"""
55+
# Create the DEVELOPMENT app when run from the command line
56+
app = create_app()
57+
with app.app_context():
58+
59+
# 1. Get the directory where THIS script (seed_users.py) lives.
60+
script_dir = os.path.dirname(__file__)
61+
62+
# 2. Build the full, absolute path to the JSON file.
63+
user_data_path = os.path.join(script_dir, "test_data/sample_user_data.json")
64+
65+
try:
66+
# You can define your default users here or import from another file
67+
with open(user_data_path, "r", encoding="utf-8") as user_file:
68+
default_users = json.load(user_file)
69+
70+
print("--- Starting user seeding ---")
71+
72+
message = seed_users(default_users)
73+
print(f"--- {message} ---")
74+
print("--- Seeding complete ---")
75+
76+
except FileNotFoundError:
77+
print(f"Error: Data file not found at '{user_data_path}'.")
78+
except json.JSONDecodeError:
79+
print(
80+
f"Error: Could not decode JSON from '{user_data_path}'. Check for syntax errors."
81+
)
82+
83+
84+
if __name__ == "__main__":
85+
main()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
{"email": "[email protected]", "password": "AdminPassword123"},
3+
{"email": "[email protected]", "password": "UserPassword456"},
4+
{"email": "[email protected]", "password": "DAYSend1991"}
5+
]

0 commit comments

Comments
 (0)