diff --git a/app/Http/Controllers/ToolController.php b/app/Http/Controllers/ToolController.php index 8d6782c..ebb7a3a 100644 --- a/app/Http/Controllers/ToolController.php +++ b/app/Http/Controllers/ToolController.php @@ -69,6 +69,12 @@ public function index(): View 'route' => 'tools.code-editor', 'icon' => 'editor', ], + [ + 'name' => 'Cron Parser', + 'description' => 'Parse and explain cron expressions', + 'route' => 'tools.cron', + 'icon' => 'clock', + ], ]; return view('home', compact('tools')); @@ -123,4 +129,9 @@ public function codeEditor(): View { return view('tools.code-editor'); } + + public function cron(): View + { + return view('tools.cron-parser'); + } } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 7de13c3..88070e4 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -84,6 +84,11 @@ @break + @case('clock') + + + + @break @endswitch
diff --git a/resources/views/tools/cron-parser.blade.php b/resources/views/tools/cron-parser.blade.php new file mode 100644 index 0000000..475ef07 --- /dev/null +++ b/resources/views/tools/cron-parser.blade.php @@ -0,0 +1,547 @@ +@extends('layouts.app') + +@section('title', 'Cron Expression Parser - Explain & Validate Cron Jobs | Dev Tools') +@section('meta_description', 'Free online cron expression parser. Understand cron syntax, validate expressions, see next run times, and get human-readable explanations of your cron schedules.') +@section('meta_keywords', 'cron parser, cron expression, cron validator, cron schedule, crontab, cron syntax, cron job, cron generator, cron explainer, cron next run') + +@push('schema') + +@endpush + +@section('content') +
+
+
+

Cron Expression Parser

+

Parse and explain cron expressions with next run times

+
+ ← Back +
+ +
+
+
+ +
+ + +
+ +
+ +
+
+ +
+

Human Readable

+

+
+ +
+
+ + + + +
+
+ +
+

Field Breakdown

+
+ +
+
+ +
+

Next Run Times

+
+ +
+
+
+ +
+
+

Common Patterns

+
+ +
+
+ +
+

Syntax Reference

+
+
+

Field Values

+ + + + + + + + + + + + + + + + + + + + + + + +
Minute0-59
Hour0-23
Day of Month1-31
Month1-12
Day of Week0-6 (Sun-Sat)
+
+
+

Special Characters

+ + + + + + + + + + + + + + + + + + + +
*Any value
,Value list (1,3,5)
-Range (1-5)
/Step (*/15)
+
+
+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index ebacbfc..ae392fe 100644 --- a/routes/web.php +++ b/routes/web.php @@ -16,6 +16,7 @@ Route::get('/hash', [ToolController::class, 'hash'])->name('hash'); Route::get('/url', [ToolController::class, 'url'])->name('url'); Route::get('/code-editor', [ToolController::class, 'codeEditor'])->name('code-editor'); + Route::get('/cron', [ToolController::class, 'cron'])->name('cron'); }); // Static Pages @@ -36,6 +37,7 @@ ['loc' => route('tools.hash'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.url'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('tools.code-editor'), 'priority' => '0.9', 'changefreq' => 'monthly'], + ['loc' => route('tools.cron'), 'priority' => '0.8', 'changefreq' => 'monthly'], ['loc' => route('about'), 'priority' => '0.5', 'changefreq' => 'monthly'], ['loc' => route('privacy'), 'priority' => '0.3', 'changefreq' => 'yearly'], ]; diff --git a/tests/Feature/WebRoutesTest.php b/tests/Feature/WebRoutesTest.php index 5acbe3a..af89929 100644 --- a/tests/Feature/WebRoutesTest.php +++ b/tests/Feature/WebRoutesTest.php @@ -28,6 +28,7 @@ public function test_home_page_displays_all_tools(): void $response->assertSee('Hash Generator'); $response->assertSee('URL Encoder'); $response->assertSee('Code Editor'); + $response->assertSee('Cron Parser'); } public function test_home_page_has_tool_links(): void @@ -44,6 +45,7 @@ public function test_home_page_has_tool_links(): void $response->assertSee('href="' . route('tools.hash') . '"', false); $response->assertSee('href="' . route('tools.url') . '"', false); $response->assertSee('href="' . route('tools.code-editor') . '"', false); + $response->assertSee('href="' . route('tools.cron') . '"', false); } public function test_csv_tool_page_loads(): void @@ -230,9 +232,29 @@ public function test_code_editor_has_required_elements(): void $response->assertSee('monaco-container'); } + public function test_cron_tool_page_loads(): void + { + $response = $this->get('/tools/cron'); + + $response->assertStatus(200); + $response->assertSee('Cron Expression Parser'); + $response->assertSee('Parse and explain cron expressions'); + } + + public function test_cron_tool_has_required_elements(): void + { + $response = $this->get('/tools/cron'); + + $response->assertStatus(200); + $response->assertSee('Cron Expression'); + $response->assertSee('Common Patterns'); + $response->assertSee('Syntax Reference'); + $response->assertSee('Next Run Times'); + } + public function test_all_pages_have_navigation(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -244,7 +266,7 @@ public function test_all_pages_have_navigation(): void public function test_all_pages_have_theme_toggle(): void { - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -257,7 +279,7 @@ public function test_all_pages_have_theme_toggle(): void public function test_all_pages_load_vite_assets(): void { // Code editor uses standalone template without Vite - $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url']; + $pages = ['/', '/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page); @@ -270,7 +292,7 @@ public function test_all_pages_load_vite_assets(): void public function test_all_tool_pages_have_back_link(): void { // Code editor uses standalone template with home link instead of back - $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url']; + $toolPages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/cron']; foreach ($toolPages as $page) { $response = $this->get($page); @@ -323,7 +345,7 @@ public function test_api_routes_reject_get_requests(): void public function test_pages_have_csrf_token(): void { - $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor']; + $pages = ['/tools/csv', '/tools/yaml', '/tools/markdown', '/tools/sql', '/tools/base64', '/tools/uuid', '/tools/hash', '/tools/url', '/tools/code-editor', '/tools/cron']; foreach ($pages as $page) { $response = $this->get($page);