diff --git a/scripts/daily-notification-test.py b/scripts/daily-notification-test.py new file mode 100755 index 0000000..fb09bd8 --- /dev/null +++ b/scripts/daily-notification-test.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 +""" +DailyNotification Plugin Automated Test Suite +Usage: python3 daily-notification-test.py [OPTIONS] +""" + +import subprocess +import time +import json +import sys +import argparse +from typing import Optional, Dict, Any, List +from dataclasses import dataclass +from enum import Enum + +class TestResult(Enum): + PASS = "PASS" + FAIL = "FAIL" + SKIP = "SKIP" + +@dataclass +class TestCase: + name: str + description: str + result: TestResult + duration: float + error: Optional[str] = None + +class DailyNotificationTester: + def __init__(self, package: str = "com.timesafari.dailynotification", verbose: bool = False): + self.package = package + self.activity = f"{package}/.MainActivity" + self.verbose = verbose + self.test_results: List[TestCase] = [] + + def log(self, message: str, level: str = "INFO"): + """Log message with timestamp""" + timestamp = time.strftime("%H:%M:%S") + if level == "ERROR": + print(f"❌ [{timestamp}] {message}") + elif level == "SUCCESS": + print(f"✅ [{timestamp}] {message}") + elif level == "WARNING": + print(f"⚠️ [{timestamp}] {message}") + elif level == "INFO": + print(f"ℹ️ [{timestamp}] {message}") + else: + print(f"[{timestamp}] {message}") + + def run_adb_command(self, command: str, capture_output: bool = True) -> subprocess.CompletedProcess: + """Run ADB command and return result""" + full_command = f"adb {command}" + if self.verbose: + self.log(f"Running: {full_command}") + + try: + return subprocess.run( + full_command, + shell=True, + capture_output=capture_output, + text=True, + timeout=30 + ) + except subprocess.TimeoutExpired: + self.log(f"Command timed out: {full_command}", "ERROR") + raise + + def is_app_running(self) -> bool: + """Check if app is currently running""" + result = self.run_adb_command(f'shell "ps | grep {self.package}"') + return result.returncode == 0 and self.package in result.stdout + + def launch_app(self) -> bool: + """Launch the app""" + self.log("Launching app...") + result = self.run_adb_command(f"shell am start -n {self.activity}") + time.sleep(3) # Wait for app to load + return self.is_app_running() + + def send_to_background(self) -> bool: + """Send app to background""" + self.log("Sending app to background...") + self.run_adb_command("shell input keyevent KEYCODE_HOME") + time.sleep(2) + return self.is_app_running() + + def force_stop_app(self) -> bool: + """Force stop the app""" + self.log("Force stopping app...") + self.run_adb_command(f"shell am force-stop {self.package}") + time.sleep(2) + return not self.is_app_running() + + def check_notification_logs(self, timeout: int = 60) -> bool: + """Check for notification success in logs""" + self.log(f"Checking notification logs (timeout: {timeout}s)...") + start_time = time.time() + + while time.time() - start_time < timeout: + result = self.run_adb_command("logcat -d") + if "Notification displayed successfully" in result.stdout: + return True + time.sleep(5) + return False + + def check_permissions(self) -> Dict[str, bool]: + """Check app permissions""" + self.log("Checking app permissions...") + result = self.run_adb_command(f"shell dumpsys package {self.package}") + + permissions = { + "notifications": "POST_NOTIFICATIONS" in result.stdout, + "exact_alarm": "SCHEDULE_EXACT_ALARM" in result.stdout, + "wake_lock": "WAKE_LOCK" in result.stdout + } + + return permissions + + def check_scheduled_alarms(self) -> bool: + """Check if any alarms are scheduled for the app""" + self.log("Checking scheduled alarms...") + result = self.run_adb_command("shell \"dumpsys alarm | grep timesafari\"") + return result.returncode == 0 and self.package in result.stdout + + def run_test(self, test_name: str, test_func, *args, **kwargs) -> TestCase: + """Run a single test case""" + self.log(f"Running test: {test_name}") + start_time = time.time() + + try: + result = test_func(*args, **kwargs) + duration = time.time() - start_time + + if result: + self.log(f"Test passed: {test_name}", "SUCCESS") + return TestCase(test_name, "", TestResult.PASS, duration) + else: + self.log(f"Test failed: {test_name}", "ERROR") + return TestCase(test_name, "", TestResult.FAIL, duration, "Test returned False") + + except Exception as e: + duration = time.time() - start_time + self.log(f"Test error: {test_name} - {str(e)}", "ERROR") + return TestCase(test_name, "", TestResult.FAIL, duration, str(e)) + + def run_test_suite(self) -> Dict[str, Any]: + """Run complete test suite""" + self.log("🧪 Starting DailyNotification Test Suite") + self.log("=" * 50) + + # Check ADB connection + result = self.run_adb_command("devices") + if "device" not in result.stdout: + self.log("No Android device connected via ADB", "ERROR") + sys.exit(1) + + self.log("ADB device connected", "SUCCESS") + + # Test 1: App Launch + test_case = self.run_test("App Launch", self.launch_app) + self.test_results.append(test_case) + + # Test 2: Background Test + test_case = self.run_test("Background Operation", self.send_to_background) + self.test_results.append(test_case) + + # Test 3: Force Stop Test + test_case = self.run_test("Force Stop", self.force_stop_app) + self.test_results.append(test_case) + + # Test 4: Permission Check + def check_permissions_test(): + permissions = self.check_permissions() + return any(permissions.values()) + + test_case = self.run_test("Permission Check", check_permissions_test) + self.test_results.append(test_case) + + # Test 5: Alarm Check + test_case = self.run_test("Alarm Scheduling", self.check_scheduled_alarms) + self.test_results.append(test_case) + + # Test 6: Notification Test (requires manual scheduling) + self.log("📱 Manual Notification Test") + self.log("⚠️ Manual step required: Schedule notification in app", "WARNING") + input("Press Enter when notification is scheduled...") + + test_case = self.run_test("Notification Delivery", self.check_notification_logs, 120) + self.test_results.append(test_case) + + return self.generate_report() + + def generate_report(self) -> Dict[str, Any]: + """Generate test report""" + total_tests = len(self.test_results) + passed_tests = sum(1 for test in self.test_results if test.result == TestResult.PASS) + failed_tests = sum(1 for test in self.test_results if test.result == TestResult.FAIL) + + report = { + "summary": { + "total": total_tests, + "passed": passed_tests, + "failed": failed_tests, + "success_rate": (passed_tests / total_tests * 100) if total_tests > 0 else 0 + }, + "tests": [ + { + "name": test.name, + "result": test.result.value, + "duration": test.duration, + "error": test.error + } + for test in self.test_results + ] + } + + return report + + def print_report(self, report: Dict[str, Any]): + """Print test report""" + self.log("\n📊 Test Results Summary:") + self.log("=" * 30) + + summary = report["summary"] + self.log(f"Total Tests: {summary['total']}") + self.log(f"Passed: {summary['passed']}") + self.log(f"Failed: {summary['failed']}") + self.log(f"Success Rate: {summary['success_rate']:.1f}%") + + self.log("\nDetailed Results:") + for test in report["tests"]: + status = "✅ PASS" if test["result"] == "PASS" else "❌ FAIL" + duration = f"({test['duration']:.1f}s)" + self.log(f"{test['name']}: {status} {duration}") + if test["error"]: + self.log(f" Error: {test['error']}", "ERROR") + +def main(): + parser = argparse.ArgumentParser(description="DailyNotification Plugin Test Suite") + parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output") + parser.add_argument("-p", "--package", default="com.timesafari.dailynotification", help="App package name") + parser.add_argument("-o", "--output", help="Output report to JSON file") + parser.add_argument("--timeout", type=int, default=120, help="Test timeout in seconds") + + args = parser.parse_args() + + tester = DailyNotificationTester(package=args.package, verbose=args.verbose) + report = tester.run_test_suite() + tester.print_report(report) + + # Save report to file if specified + if args.output: + with open(args.output, 'w') as f: + json.dump(report, f, indent=2) + tester.log(f"Report saved to: {args.output}") + + # Exit with error code if any test failed + if report["summary"]["failed"] > 0: + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/scripts/daily-notification-test.sh b/scripts/daily-notification-test.sh new file mode 100755 index 0000000..17ca17d --- /dev/null +++ b/scripts/daily-notification-test.sh @@ -0,0 +1,213 @@ +#!/bin/bash +# DailyNotification Plugin Test Script +# Usage: ./daily-notification-test.sh + +set -e + +# Configuration +APP_PACKAGE="com.timesafari.dailynotification" +APP_ACTIVITY=".MainActivity" +TEST_TIMEOUT=120 # 2 minutes +LOG_TAG="DailyNotification" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +# Function to check if app is running +check_app_running() { + adb shell "ps | grep $APP_PACKAGE" > /dev/null 2>&1 +} + +# Function to wait for app to be ready +wait_for_app() { + print_status $YELLOW "⏳ Waiting for app to be ready..." + sleep 3 +} + +# Function to schedule notification (manual step) +schedule_notification() { + print_status $BLUE "📅 Scheduling test notification..." + print_status $YELLOW "⚠️ Manual step: Schedule notification in app UI" + print_status $YELLOW " - Tap 'Test Notification' button" + print_status $YELLOW " - Wait for 'Notification scheduled' message" + read -p "Press Enter when notification is scheduled..." +} + +# Function to check notification in logs +check_notification_logs() { + local timeout=$1 + local start_time=$(date +%s) + + print_status $BLUE "👀 Monitoring logs for notification delivery..." + + while [ $(($(date +%s) - start_time)) -lt $timeout ]; do + if adb logcat -d | grep -q "Notification displayed successfully"; then + print_status $GREEN "✅ Notification displayed successfully" + return 0 + fi + sleep 5 + done + + print_status $RED "❌ Notification not found in logs" + return 1 +} + +# Function to run ADB command and check result +run_adb_command() { + local command=$1 + local description=$2 + + print_status $BLUE "🔧 $description" + if adb $command; then + print_status $GREEN "✅ $description - Success" + return 0 + else + print_status $RED "❌ $description - Failed" + return 1 + fi +} + +# Main test function +main() { + print_status $BLUE "🧪 Starting DailyNotification Plugin Tests" + print_status $BLUE "==========================================" + + # Check ADB connection + if ! adb devices | grep -q "device$"; then + print_status $RED "❌ No Android device connected via ADB" + exit 1 + fi + + print_status $GREEN "✅ ADB device connected" + + # Test 1: App Launch + print_status $BLUE "🚀 Test 1: App Launch" + if run_adb_command "shell am start -n $APP_PACKAGE/$APP_ACTIVITY" "Launching app"; then + wait_for_app + if check_app_running; then + print_status $GREEN "✅ App launched and running" + else + print_status $RED "❌ App failed to start" + exit 1 + fi + else + exit 1 + fi + + # Test 2: Background Test + print_status $BLUE "🔄 Test 2: Background Notification Test" + schedule_notification + + print_status $BLUE "📱 Sending app to background..." + if run_adb_command "shell input keyevent KEYCODE_HOME" "Send to background"; then + sleep 2 + if check_app_running; then + print_status $GREEN "✅ App running in background" + else + print_status $RED "❌ App not running in background" + exit 1 + fi + else + exit 1 + fi + + # Test 3: Wait for notification + print_status $BLUE "⏰ Test 3: Waiting for notification ($TEST_TIMEOUT seconds)..." + print_status $YELLOW "👀 Watch for notification in system panel" + + if check_notification_logs $TEST_TIMEOUT; then + print_status $GREEN "✅ Notification test passed" + else + print_status $RED "❌ Notification test failed or timed out" + fi + + # Test 4: Force Stop Test + print_status $BLUE "🛑 Test 4: Force Stop Test (Expected Failure)" + schedule_notification + + print_status $BLUE "💀 Force stopping app..." + if run_adb_command "shell am force-stop $APP_PACKAGE" "Force stop app"; then + sleep 2 + if check_app_running; then + print_status $RED "❌ App still running after force stop" + exit 1 + else + print_status $GREEN "✅ App successfully force stopped" + fi + else + exit 1 + fi + + print_status $BLUE "⏰ Waiting for notification (should NOT appear)..." + sleep 60 + + if adb logcat -d | grep -q "Notification displayed successfully"; then + print_status $RED "❌ Notification appeared after force stop (unexpected)" + else + print_status $GREEN "✅ No notification after force stop (expected)" + fi + + # Test 5: Permission Check + print_status $BLUE "🔐 Test 5: Permission Status Check" + run_adb_command "shell \"dumpsys notification | grep -A5 -B5 $APP_PACKAGE\"" "Check notification settings" + + # Test 6: Alarm Status Check + print_status $BLUE "⏰ Test 6: Alarm Status Check" + run_adb_command "shell \"dumpsys alarm | grep $APP_PACKAGE\"" "Check scheduled alarms" + + print_status $GREEN "🎉 All tests completed!" + print_status $BLUE "📊 Check the results above for any failures" +} + +# Help function +show_help() { + echo "DailyNotification Plugin Test Script" + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " -h, --help Show this help message" + echo " -v, --verbose Enable verbose output" + echo " -t, --timeout Set test timeout in seconds (default: 120)" + echo "" + echo "Examples:" + echo " $0 # Run all tests" + echo " $0 -t 60 # Run with 60 second timeout" + echo " $0 -v # Run with verbose output" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -v|--verbose) + set -x + shift + ;; + -t|--timeout) + TEST_TIMEOUT="$2" + shift 2 + ;; + *) + print_status $RED "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Run main function +main diff --git a/scripts/reboot-test.sh b/scripts/reboot-test.sh new file mode 100755 index 0000000..2f68399 --- /dev/null +++ b/scripts/reboot-test.sh @@ -0,0 +1,249 @@ +#!/bin/bash +# Reboot Recovery Test Script for DailyNotification Plugin +# Usage: ./reboot-test.sh + +set -e + +# Configuration +APP_PACKAGE="com.timesafari.dailynotification" +APP_ACTIVITY=".MainActivity" +BOOT_WAIT_TIME=60 # Wait 60 seconds for boot completion +RECOVERY_TIMEOUT=30 # Wait 30 seconds for recovery + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +# Function to wait for device to be ready +wait_for_device() { + print_status $YELLOW "⏳ Waiting for device to be ready..." + adb wait-for-device + sleep 5 + + # Wait for boot completion + local boot_completed=false + local attempts=0 + local max_attempts=12 # 60 seconds total + + while [ $attempts -lt $max_attempts ]; do + if adb shell getprop sys.boot_completed 2>/dev/null | grep -q "1"; then + boot_completed=true + break + fi + print_status $YELLOW " Boot not complete, waiting... ($((attempts + 1))/$max_attempts)" + sleep 5 + attempts=$((attempts + 1)) + done + + if [ "$boot_completed" = true ]; then + print_status $GREEN "✅ Device boot completed" + sleep 5 # Additional wait for services to start + else + print_status $RED "❌ Device boot timeout" + exit 1 + fi +} + +# Function to schedule notification (manual step) +schedule_notification() { + print_status $BLUE "📅 Scheduling test notification..." + adb shell am start -n $APP_PACKAGE/$APP_ACTIVITY + sleep 3 + + print_status $YELLOW "⚠️ Manual step: Schedule notification in app" + print_status $YELLOW " - Tap 'Test Notification' button" + print_status $YELLOW " - Wait for 'Notification scheduled for [time]!' message" + print_status $YELLOW " - Note the scheduled time (5 minutes from now)" + read -p "Press Enter when notification is scheduled..." +} + +# Function to check recovery logs +check_recovery_logs() { + print_status $BLUE "🔍 Checking recovery logs..." + + # Check for boot receiver activation + if adb logcat -d | grep -q "Device boot completed - restoring notifications"; then + print_status $GREEN "✅ Boot receiver activated" + else + print_status $RED "❌ Boot receiver not activated" + return 1 + fi + + # Check for recovery completion + if adb logcat -d | grep -q "Notification recovery completed successfully"; then + print_status $GREEN "✅ Recovery completed successfully" + return 0 + else + print_status $RED "❌ Recovery not completed" + return 1 + fi +} + +# Function to check scheduled alarms +check_scheduled_alarms() { + print_status $BLUE "⏰ Checking scheduled alarms..." + + local alarm_output=$(adb shell "dumpsys alarm | grep timesafari" 2>/dev/null || true) + + if [ -n "$alarm_output" ]; then + print_status $GREEN "✅ Alarms found:" + echo "$alarm_output" + return 0 + else + print_status $RED "❌ No alarms found" + return 1 + fi +} + +# Function to check boot receiver registration +check_boot_receiver() { + print_status $BLUE "🔧 Checking boot receiver registration..." + + local receiver_output=$(adb shell "dumpsys package $APP_PACKAGE | grep -A10 -B10 receiver" 2>/dev/null || true) + + if echo "$receiver_output" | grep -q "BootReceiver"; then + print_status $GREEN "✅ Boot receiver registered" + return 0 + else + print_status $RED "❌ Boot receiver not registered" + return 1 + fi +} + +# Function to reboot device +reboot_device() { + print_status $BLUE "🔄 Rebooting device..." + print_status $YELLOW " This will take about 2-3 minutes..." + + adb reboot + wait_for_device +} + +# Function to run ADB command and check result +run_adb_command() { + local command=$1 + local description=$2 + + print_status $BLUE "🔧 $description" + if adb $command; then + print_status $GREEN "✅ $description - Success" + return 0 + else + print_status $RED "❌ $description - Failed" + return 1 + fi +} + +# Main test function +main() { + print_status $BLUE "🔄 Starting Reboot Recovery Test" + print_status $BLUE "================================" + + # Check ADB connection + if ! adb devices | grep -q "device$"; then + print_status $RED "❌ No Android device connected via ADB" + exit 1 + fi + + print_status $GREEN "✅ ADB device connected" + + # Pre-reboot checks + print_status $BLUE "🔍 Pre-reboot checks..." + + # Check boot receiver registration + if ! check_boot_receiver; then + print_status $RED "❌ Boot receiver not properly registered" + exit 1 + fi + + # Schedule notification + schedule_notification + + # Verify initial scheduling + print_status $BLUE "📋 Verifying initial scheduling..." + if check_scheduled_alarms; then + print_status $GREEN "✅ Initial scheduling successful" + else + print_status $RED "❌ Initial scheduling failed" + exit 1 + fi + + # Reboot device + reboot_device + + # Post-reboot checks + print_status $BLUE "🔍 Post-reboot checks..." + + # Check recovery logs + if check_recovery_logs; then + print_status $GREEN "✅ Recovery successful" + else + print_status $RED "❌ Recovery failed" + exit 1 + fi + + # Verify alarms restored + if check_scheduled_alarms; then + print_status $GREEN "✅ Alarms restored successfully" + else + print_status $RED "❌ Alarms not restored" + exit 1 + fi + + # Final status + print_status $GREEN "🎉 Reboot recovery test completed successfully!" + print_status $BLUE "⏰ Wait for the scheduled notification to appear (5 minutes from original schedule)" + print_status $YELLOW "👀 Monitor notification panel for the test notification" +} + +# Help function +show_help() { + echo "Reboot Recovery Test Script" + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " -h, --help Show this help message" + echo " -v, --verbose Enable verbose output" + echo " -w, --wait Set boot wait time in seconds (default: 60)" + echo "" + echo "Examples:" + echo " $0 # Run reboot test" + echo " $0 -w 90 # Run with 90 second boot wait" + echo " $0 -v # Run with verbose output" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -v|--verbose) + set -x + shift + ;; + -w|--wait) + BOOT_WAIT_TIME="$2" + shift 2 + ;; + *) + print_status $RED "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Run main function +main