Replace logo with client-supplied artwork; add Nablus workshop registration form

- public/images/logo.png replaced with the client's professionally-designed
  version, cropped to remove excess background margin (used sitewide via
  logo.blade.php / app-logo.blade.php / app-logo-icon.blade.php)
- New standalone, unlinked registration form at /forms/nablus-workshop for a
  one-off workshop Libra is co-hosting with Smart Business Center, replicating
  a ClickUp form the client previously used but with Libra's own branding.
  Submissions email info@libra.adv.ps and redirect to /about. No nav/footer
  link, no DB storage, no captcha (PRD v1.3).
- Tasks 17 (parent), 17-1 (Mailable + email template), 17-2 (page/route/form)
  taken through product-definition -> task-readiness -> dev-implement -> dev-qa,
  all Done. 11 new tests passing; full suite run clean of new regressions
  (69 pre-existing unrelated failures, documented in docs/tasks/17.md).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Naser Mansour
2026-09-27 23:56:50 +03:00
parent 1b66e0b6ff
commit 690c22395f
14 changed files with 745 additions and 0 deletions
@@ -0,0 +1,87 @@
<?php
use App\Mail\WorkshopRegistrationMail;
use Illuminate\Support\Facades\Mail;
use Livewire\Volt\Volt;
beforeEach(function () {
Mail::fake();
});
test('registration page is publicly reachable without site navigation or footer', function () {
$this->get('/forms/nablus-workshop')
->assertOk()
->assertDontSee('x-navigation', false)
->assertDontSee('x-footer', false);
});
test('navigation and footer components do not link to the workshop page', function () {
$navigation = file_get_contents(resource_path('views/components/navigation.blade.php'));
$footer = file_get_contents(resource_path('views/components/footer.blade.php'));
expect($navigation)->not->toContain('nablus-workshop');
expect($footer)->not->toContain('nablus-workshop');
});
test('valid submission with blank email sends workshop registration mail and redirects to about', function () {
Volt::test('pages.forms.nablus-workshop')
->set('fullName', 'سارة أحمد')
->set('contactNumber', '0599123456')
->set('email', '')
->call('register')
->assertHasNoErrors()
->assertRedirect(route('about'));
Mail::assertQueued(WorkshopRegistrationMail::class, function ($mail) {
return $mail->fullName === 'سارة أحمد'
&& $mail->contactNumber === '0599123456'
&& $mail->email === null;
});
});
test('blank full name fails validation and does not send mail', function () {
Volt::test('pages.forms.nablus-workshop')
->set('fullName', '')
->set('contactNumber', '0599123456')
->call('register')
->assertHasErrors(['fullName']);
Mail::assertNothingSent();
Mail::assertNothingQueued();
});
test('blank contact number fails validation and does not send mail', function () {
Volt::test('pages.forms.nablus-workshop')
->set('fullName', 'سارة أحمد')
->set('contactNumber', '')
->call('register')
->assertHasErrors(['contactNumber']);
Mail::assertNothingSent();
Mail::assertNothingQueued();
});
test('invalid email fails validation and does not send mail', function () {
Volt::test('pages.forms.nablus-workshop')
->set('fullName', 'سارة أحمد')
->set('contactNumber', '0599123456')
->set('email', 'not-an-email')
->call('register')
->assertHasErrors(['email']);
Mail::assertNothingSent();
Mail::assertNothingQueued();
});
test('valid email is passed through to the mailable', function () {
Volt::test('pages.forms.nablus-workshop')
->set('fullName', 'سارة أحمد')
->set('contactNumber', '0599123456')
->set('email', 'sara@example.com')
->call('register')
->assertHasNoErrors();
Mail::assertQueued(WorkshopRegistrationMail::class, function ($mail) {
return $mail->email === 'sara@example.com';
});
});