diff --git a/dashboard/habits.json b/dashboard/habits.json new file mode 100644 index 0000000..e54d278 --- /dev/null +++ b/dashboard/habits.json @@ -0,0 +1,4 @@ +{ + "lastUpdated": "2026-02-10T10:57:00.000Z", + "habits": [] +} diff --git a/dashboard/test_habits_schema.py b/dashboard/test_habits_schema.py new file mode 100644 index 0000000..d7ae33e --- /dev/null +++ b/dashboard/test_habits_schema.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +""" +Test suite for habits.json schema validation +""" +import json +import os +from datetime import datetime + + +def test_habits_file_exists(): + """Test that habits.json file exists""" + assert os.path.exists('dashboard/habits.json'), "habits.json should exist in dashboard/" + print("✓ habits.json file exists") + + +def test_valid_json(): + """Test that habits.json is valid JSON""" + try: + with open('dashboard/habits.json', 'r') as f: + data = json.load(f) + print("✓ habits.json is valid JSON") + return data + except json.JSONDecodeError as e: + raise AssertionError(f"habits.json is not valid JSON: {e}") + + +def test_root_structure(data): + """Test that root structure has required fields""" + assert 'lastUpdated' in data, "Root should have 'lastUpdated' field" + assert 'habits' in data, "Root should have 'habits' field" + print("✓ Root structure has lastUpdated and habits fields") + + +def test_last_updated_format(data): + """Test that lastUpdated is a valid ISO timestamp""" + try: + datetime.fromisoformat(data['lastUpdated'].replace('Z', '+00:00')) + print("✓ lastUpdated is valid ISO timestamp") + except (ValueError, AttributeError) as e: + raise AssertionError(f"lastUpdated is not a valid ISO timestamp: {e}") + + +def test_habits_is_array(data): + """Test that habits is an array""" + assert isinstance(data['habits'], list), "habits should be an array" + print("✓ habits is an array") + + +def test_habit_schema(): + """Test habit schema structure with sample data""" + # Sample habit to validate schema + sample_habit = { + "id": "habit-123", + "name": "Bazin", + "frequency": "daily", + "createdAt": "2026-02-10T10:57:00.000Z", + "completions": ["2026-02-10T10:00:00.000Z", "2026-02-09T10:00:00.000Z"] + } + + # Validate required fields + required_fields = ['id', 'name', 'frequency', 'createdAt', 'completions'] + for field in required_fields: + assert field in sample_habit, f"Habit should have '{field}' field" + + # Validate types + assert isinstance(sample_habit['id'], str), "id should be string" + assert isinstance(sample_habit['name'], str), "name should be string" + assert sample_habit['frequency'] in ['daily', 'weekly'], "frequency should be 'daily' or 'weekly'" + assert isinstance(sample_habit['completions'], list), "completions should be array" + + # Validate ISO dates + datetime.fromisoformat(sample_habit['createdAt'].replace('Z', '+00:00')) + for completion in sample_habit['completions']: + datetime.fromisoformat(completion.replace('Z', '+00:00')) + + print("✓ Habit schema structure is valid") + + +def test_initial_state(data): + """Test that initial file has empty habits array""" + assert len(data['habits']) == 0, "Initial habits array should be empty" + print("✓ Initial habits array is empty") + + +def run_all_tests(): + """Run all schema validation tests""" + print("Running habits.json schema validation tests...\n") + + try: + test_habits_file_exists() + data = test_valid_json() + test_root_structure(data) + test_last_updated_format(data) + test_habits_is_array(data) + test_habit_schema() + test_initial_state(data) + + print("\n✅ All tests passed!") + return True + except AssertionError as e: + print(f"\n❌ Test failed: {e}") + return False + except Exception as e: + print(f"\n❌ Unexpected error: {e}") + return False + + +if __name__ == '__main__': + success = run_all_tests() + exit(0 if success else 1)