Restructure src/ and tests/ from package-by-type to package-by-domain
All checks were successful
CI / Coding Standards (push) Successful in 43s
CI / PHPStan (push) Successful in 52s
CI / Tests (PHP 8.1) (push) Successful in 47s
CI / Tests (PHP 8.2) (push) Successful in 49s
CI / Tests (PHP 8.3) (push) Successful in 37s
CI / No Debug Code (push) Successful in 2s
All checks were successful
CI / Coding Standards (push) Successful in 43s
CI / PHPStan (push) Successful in 52s
CI / Tests (PHP 8.1) (push) Successful in 47s
CI / Tests (PHP 8.2) (push) Successful in 49s
CI / Tests (PHP 8.3) (push) Successful in 37s
CI / No Debug Code (push) Successful in 2s
All classes are now organised by domain (Availability, Booking, Auth). Each domain package contains its value object, repository, admin controller, REST endpoint, and any shortcode pages under a matching sub-namespace. Cross-cutting wiring (Plugin, AdminMenu, RestRegistrar, ShortcodeRegistrar, Schema) lives at src/ root. Tests mirror the domain structure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
126
tests/Unit/Booking/BookingRepositoryTest.php
Normal file
126
tests/Unit/Booking/BookingRepositoryTest.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Unsupervised\Schedular\Tests\Unit\Booking;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use Mockery;
|
||||
use Unsupervised\Schedular\Booking\BookingRepository;
|
||||
use Unsupervised\Schedular\Booking\Lesson;
|
||||
use Unsupervised\Schedular\Tests\Unit\TestCase;
|
||||
|
||||
class BookingRepositoryTest extends TestCase
|
||||
{
|
||||
private \wpdb $db;
|
||||
private BookingRepository $repo;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->db = Mockery::mock(\wpdb::class);
|
||||
$this->db->prefix = 'wp_';
|
||||
$this->repo = new BookingRepository($this->db);
|
||||
}
|
||||
|
||||
public function testInsertCallsWpdbInsertAndReturnsId(): void
|
||||
{
|
||||
Functions\expect('current_time')->with('mysql')->andReturn('2026-04-01 12:00:00');
|
||||
|
||||
$this->db->shouldReceive('insert')
|
||||
->once()
|
||||
->with(
|
||||
'wp_us_lessons',
|
||||
Mockery::on(static function (array $data): bool {
|
||||
return $data['slot_id'] === 10
|
||||
&& $data['student_id'] === 5
|
||||
&& $data['status'] === Lesson::STATUS_PENDING;
|
||||
}),
|
||||
['%d', '%d', '%d', '%s', '%s', '%s']
|
||||
);
|
||||
|
||||
$this->db->insert_id = 77;
|
||||
|
||||
$lesson = new Lesson(slotId: 10, studentId: 5, instructorId: 3);
|
||||
$result = $this->repo->insert($lesson);
|
||||
|
||||
self::assertSame(77, $result);
|
||||
}
|
||||
|
||||
public function testFindByIdReturnsNullWhenNotFound(): void
|
||||
{
|
||||
$this->db->shouldReceive('prepare')->andReturn('SELECT ...');
|
||||
$this->db->shouldReceive('get_row')->andReturn(null);
|
||||
|
||||
self::assertNull($this->repo->findById(99));
|
||||
}
|
||||
|
||||
public function testFindByIdReturnsLesson(): void
|
||||
{
|
||||
$row = (object) [
|
||||
'id' => '15',
|
||||
'slot_id' => '10',
|
||||
'student_id' => '5',
|
||||
'instructor_id' => '3',
|
||||
'status' => 'pending',
|
||||
'notes' => null,
|
||||
];
|
||||
|
||||
$this->db->shouldReceive('prepare')->andReturn('SELECT ...');
|
||||
$this->db->shouldReceive('get_row')->andReturn($row);
|
||||
|
||||
$lesson = $this->repo->findById(15);
|
||||
|
||||
self::assertInstanceOf(Lesson::class, $lesson);
|
||||
self::assertSame(15, $lesson->id);
|
||||
}
|
||||
|
||||
public function testUpdateStatusReturnsFalseForInvalidStatus(): void
|
||||
{
|
||||
$result = $this->repo->updateStatus(1, 'invalid');
|
||||
self::assertFalse($result);
|
||||
}
|
||||
|
||||
public function testUpdateStatusCallsWpdbUpdate(): void
|
||||
{
|
||||
$this->db->shouldReceive('update')
|
||||
->once()
|
||||
->with(
|
||||
'wp_us_lessons',
|
||||
['status' => Lesson::STATUS_CONFIRMED],
|
||||
['id' => 1],
|
||||
['%s'],
|
||||
['%d']
|
||||
)
|
||||
->andReturn(1);
|
||||
|
||||
self::assertTrue($this->repo->updateStatus(1, Lesson::STATUS_CONFIRMED));
|
||||
}
|
||||
|
||||
public function testUpdateStatusReturnsFalseWhenDbFails(): void
|
||||
{
|
||||
$this->db->shouldReceive('update')->andReturn(0);
|
||||
|
||||
self::assertFalse($this->repo->updateStatus(1, Lesson::STATUS_CONFIRMED));
|
||||
}
|
||||
|
||||
public function testFindByStudentReturnsLessons(): void
|
||||
{
|
||||
$row = (object) [
|
||||
'id' => '1',
|
||||
'slot_id' => '2',
|
||||
'student_id' => '5',
|
||||
'instructor_id' => '3',
|
||||
'status' => 'pending',
|
||||
'notes' => null,
|
||||
];
|
||||
|
||||
$this->db->shouldReceive('prepare')->andReturn('SELECT ...');
|
||||
$this->db->shouldReceive('get_results')->andReturn([$row]);
|
||||
|
||||
$lessons = $this->repo->findByStudent(5);
|
||||
|
||||
self::assertCount(1, $lessons);
|
||||
self::assertInstanceOf(Lesson::class, $lessons[0]);
|
||||
}
|
||||
}
|
||||
68
tests/Unit/Booking/LessonTest.php
Normal file
68
tests/Unit/Booking/LessonTest.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Unsupervised\Schedular\Tests\Unit\Booking;
|
||||
|
||||
use Unsupervised\Schedular\Booking\Lesson;
|
||||
use Unsupervised\Schedular\Tests\Unit\TestCase;
|
||||
|
||||
class LessonTest extends TestCase
|
||||
{
|
||||
public function testStatusConstants(): void
|
||||
{
|
||||
self::assertSame('pending', Lesson::STATUS_PENDING);
|
||||
self::assertSame('confirmed', Lesson::STATUS_CONFIRMED);
|
||||
self::assertSame('cancelled', Lesson::STATUS_CANCELLED);
|
||||
}
|
||||
|
||||
public function testValidStatusesContainsAllThree(): void
|
||||
{
|
||||
self::assertContains(Lesson::STATUS_PENDING, Lesson::VALID_STATUSES);
|
||||
self::assertContains(Lesson::STATUS_CONFIRMED, Lesson::VALID_STATUSES);
|
||||
self::assertContains(Lesson::STATUS_CANCELLED, Lesson::VALID_STATUSES);
|
||||
self::assertCount(3, Lesson::VALID_STATUSES);
|
||||
}
|
||||
|
||||
public function testConstructorDefaults(): void
|
||||
{
|
||||
$lesson = new Lesson(slotId: 1, studentId: 2, instructorId: 3);
|
||||
|
||||
self::assertSame(Lesson::STATUS_PENDING, $lesson->status);
|
||||
self::assertNull($lesson->notes);
|
||||
self::assertNull($lesson->id);
|
||||
}
|
||||
|
||||
public function testFromRowMapsCorrectly(): void
|
||||
{
|
||||
$row = (object) [
|
||||
'id' => '99',
|
||||
'slot_id' => '10',
|
||||
'student_id' => '20',
|
||||
'instructor_id' => '30',
|
||||
'status' => 'confirmed',
|
||||
'notes' => 'Bring your guitar.',
|
||||
];
|
||||
|
||||
$lesson = Lesson::fromRow($row);
|
||||
|
||||
self::assertSame(99, $lesson->id);
|
||||
self::assertSame(10, $lesson->slotId);
|
||||
self::assertSame(20, $lesson->studentId);
|
||||
self::assertSame(30, $lesson->instructorId);
|
||||
self::assertSame('confirmed', $lesson->status);
|
||||
self::assertSame('Bring your guitar.', $lesson->notes);
|
||||
}
|
||||
|
||||
public function testToArrayContainsExpectedKeys(): void
|
||||
{
|
||||
$lesson = new Lesson(1, 2, 3, Lesson::STATUS_PENDING, 'Note', 5);
|
||||
$arr = $lesson->toArray();
|
||||
|
||||
self::assertArrayHasKey('id', $arr);
|
||||
self::assertArrayHasKey('slot_id', $arr);
|
||||
self::assertArrayHasKey('student_id', $arr);
|
||||
self::assertArrayHasKey('instructor_id', $arr);
|
||||
self::assertArrayHasKey('status', $arr);
|
||||
self::assertArrayHasKey('notes', $arr);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user