dbMock = $this->mock(Database::class); $this->dbMock->begin->returns($this->mock(\JKingWeb\Arsse\Db\Transaction::class)); } protected function prepTest(): Driver { Arsse::$db = $this->dbMock->get(); return new Driver; } public function testConstruct(): void { $this->assertInstanceOf(DriverInterface::class, new Driver); } public function testFetchDriverName(): void { $this->assertTrue(strlen(Driver::driverName()) > 0); } /** * @dataProvider provideAuthentication * @group slow */ public function testAuthenticateAUser(string $user, $password, bool $exp): void { $this->dbMock->userPasswordGet->with("john.doe@example.com")->returns('$2y$10$1zbqRJhxM8uUjeSBPp4IhO90xrqK0XjEh9Z16iIYEFRV4U.zeAFom'); // hash of "secret" $this->dbMock->userPasswordGet->with("jane.doe@example.com")->returns('$2y$10$bK1ljXfTSyc2D.NYvT.Eq..OpehLRXVbglW.23ihVuyhgwJCd.7Im'); // hash of "superman" $this->dbMock->userPasswordGet->with("owen.hardy@example.com")->returns(""); $this->dbMock->userPasswordGet->with("kira.nerys@example.com")->throws(new \JKingWeb\Arsse\User\ExceptionConflict("doesNotExist")); $this->dbMock->userPasswordGet->with("007@example.com")->returns(null); $this->assertSame($exp, $this->prepTest()->auth($user, $password)); } public function provideAuthentication(): iterable { $john = "john.doe@example.com"; $jane = "jane.doe@example.com"; $owen = "owen.hardy@example.com"; $kira = "kira.nerys@example.com"; $bond = "007@example.com"; return [ [$john, "secret", true], [$jane, "superman", true], [$owen, "", true], [$kira, "ashalla", false], [$john, "top secret", false], [$jane, "clark kent", false], [$owen, "watchmaker", false], [$kira, "singha", false], [$john, "", false], [$jane, "", false], [$kira, "", false], [$bond, "for England", false], [$bond, "", false], ]; } public function testListUsers(): void { $john = "john.doe@example.com"; $jane = "jane.doe@example.com"; $this->dbMock->userList->returns([$john, $jane])->returns([$jane, $john]); $driver = $this->prepTest(); $this->assertSame([$john, $jane], $driver->userList()); $this->assertSame([$jane, $john], $driver->userList()); $this->dbMock->userList->times(2)->called(); } public function testAddAUser(): void { $john = "john.doe@example.com"; $this->dbMock->userAdd->does(function($user, $pass) { return $pass; }); $driver = $this->prepTest(); $this->assertNull($driver->userAdd($john)); $this->assertNull($driver->userAdd($john, null)); $this->assertSame("secret", $driver->userAdd($john, "secret")); $this->dbMock->userAdd->calledWith($john, "secret"); $this->dbMock->userAdd->called(); } public function testRenameAUser(): void { $john = "john.doe@example.com"; $this->dbMock->userExists->returns(true); $this->assertTrue($this->prepTest()->userRename($john, "jane.doe@example.com")); $this->assertFalse($this->prepTest()->userRename($john, $john)); $this->dbMock->userExists->times(2)->calledWith($john); } public function testRenameAMissingUser(): void { $john = "john.doe@example.com"; $this->dbMock->userExists->returns(false); $this->assertException("doesNotExist", "User", "ExceptionConflict"); $this->prepTest()->userRename($john, "jane.doe@example.com"); } public function testRemoveAUser(): void { $john = "john.doe@example.com"; $this->dbMock->userRemove->returns(true)->throws(new \JKingWeb\Arsse\User\ExceptionConflict("doesNotExist")); $driver = $this->prepTest(); $this->assertTrue($driver->userRemove($john)); $this->dbMock->userRemove->calledWith($john); $this->assertException("doesNotExist", "User", "ExceptionConflict"); try { $this->assertFalse($driver->userRemove($john)); } finally { $this->dbMock->userRemove->times(2)->calledWith($john); } } public function testSetAPassword(): void { $john = "john.doe@example.com"; $this->dbMock->userExists->returns(true); $this->assertSame("superman", $this->prepTest()->userPasswordSet($john, "superman")); $this->assertSame(null, $this->prepTest()->userPasswordSet($john, null)); $this->dbMock->userPasswordSet->never()->called(); } public function testSetAPasswordForAMssingUser(): void { $this->dbMock->userExists->returns(false); $this->assertException("doesNotExist", "User", "ExceptionConflict"); $this->prepTest()->userPasswordSet("john.doe@example.com", "secret"); } public function testUnsetAPassword(): void { $this->dbMock->userExists->returns(true); $this->assertTrue($this->prepTest()->userPasswordUnset("john.doe@example.com")); $this->dbMock->userPasswordSet->never()->called(); } public function testUnsetAPasswordForAMssingUser(): void { $this->dbMock->userExists->returns(false); $this->assertException("doesNotExist", "User", "ExceptionConflict"); $this->prepTest()->userPasswordUnset("john.doe@example.com"); } public function testGetUserProperties(): void { $this->dbMock->userExists->returns(true); $this->assertSame([], $this->prepTest()->userPropertiesGet("john.doe@example.com")); $this->dbMock->userExists->calledWith("john.doe@example.com"); } public function testGetPropertiesForAMissingUser(): void { $this->dbMock->userExists->returns(false); $this->assertException("doesNotExist", "User", "ExceptionConflict"); try { $this->prepTest()->userPropertiesGet("john.doe@example.com"); } finally { $this->dbMock->userExists->calledWith("john.doe@example.com"); } } public function testSetUserProperties(): void { $in = ['admin' => true]; $this->dbMock->userExists->returns(true); $this->assertSame($in, $this->prepTest()->userPropertiesSet("john.doe@example.com", $in)); $this->dbMock->userExists->calledWith("john.doe@example.com"); } public function testSetPropertiesForAMissingUser(): void { $this->dbMock->userExists->returns(false); $this->assertException("doesNotExist", "User", "ExceptionConflict"); try { $this->prepTest()->userPropertiesSet("john.doe@example.com", ['admin' => true]); } finally { $this->dbMock->userExists->calledWith("john.doe@example.com"); } } }