gate = new ChildLoginGate(); } /** * @param array $children User IDs flagged as child accounts. */ private function stubChildren(array $children): void { Functions\when('get_user_meta')->alias( static fn (int $userId, string $key, bool $single = false): string => in_array($userId, $children, true) ? '1' : '' ); } private function user(int $id): \WP_User { $user = Mockery::mock(\WP_User::class); $user->ID = $id; return $user; } public function testRegisterHooksBothFilters(): void { $this->gate->register(); self::assertNotFalse(Filters\has('wp_authenticate_user', [$this->gate, 'blockChildLogin'])); self::assertNotFalse(Filters\has('user_has_cap', [$this->gate, 'withholdBooking'])); } public function testChildAccountCannotAuthenticate(): void { $this->stubChildren([42]); $result = $this->gate->blockChildLogin($this->user(42)); self::assertInstanceOf(\WP_Error::class, $result); self::assertSame('us_child_account', $result->get_error_code()); } public function testOrdinaryStudentPassesThrough(): void { $this->stubChildren([42]); $user = $this->user(9); self::assertSame($user, $this->gate->blockChildLogin($user)); } public function testAnEarlierAuthenticationErrorIsPassedThroughUntouched(): void { $this->stubChildren([42]); $error = new \WP_Error('bad_password', 'Nope.'); self::assertSame($error, $this->gate->blockChildLogin($error)); } public function testBookingCapabilityIsWithheldFromAChild(): void { $this->stubChildren([42]); $caps = $this->gate->withholdBooking( ['read' => true, RoleManager::CAP_BOOK_LESSON => true], [], [], $this->user(42) ); self::assertArrayNotHasKey(RoleManager::CAP_BOOK_LESSON, $caps); self::assertTrue($caps['read']); } public function testBookingCapabilityIsLeftAloneForAnOrdinaryStudent(): void { $this->stubChildren([42]); $caps = $this->gate->withholdBooking( [RoleManager::CAP_BOOK_LESSON => true], [], [], $this->user(9) ); self::assertTrue($caps[RoleManager::CAP_BOOK_LESSON]); } public function testNonUserSubjectIsIgnored(): void { $caps = [RoleManager::CAP_BOOK_LESSON => true]; self::assertSame($caps, $this->gate->withholdBooking($caps, [], [], null)); } public function testGuardianServiceIsTheSingleSourceOfTheChildFlag(): void { $this->stubChildren([42]); self::assertTrue(GuardianService::isChild(42)); self::assertFalse(GuardianService::isChild(9)); } }