From 2348786a9232f45e05a6fa4d7cb52688ed77d4a4 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sat, 27 Feb 2021 15:24:02 -0500 Subject: [PATCH] Start on replacing Phake with Phony --- tests/bootstrap.php | 2 +- tests/cases/CLI/TestCLI.php | 190 +++++++++--------- tests/cases/Conf/TestConf.php | 4 +- tests/cases/Database/AbstractTest.php | 3 +- tests/cases/Database/SeriesSubscription.php | 26 ++- tests/cases/Database/TestDatabase.php | 16 +- tests/cases/Db/BaseDriver.php | 6 +- tests/cases/Db/BaseResult.php | 8 +- tests/cases/Db/BaseStatement.php | 8 +- tests/cases/Db/BaseUpdate.php | 6 +- tests/cases/Db/SQLite3/TestCreation.php | 6 +- tests/cases/Db/SQLite3PDO/TestCreation.php | 6 +- tests/cases/Db/TestTransaction.php | 41 ++-- tests/cases/Exception/TestException.php | 13 +- tests/cases/Feed/TestFeed.php | 34 ++-- tests/cases/Feed/TestFetching.php | 2 +- tests/cases/ImportExport/TestFile.php | 22 +- tests/cases/ImportExport/TestImportExport.php | 40 ++-- tests/cases/ImportExport/TestOPML.php | 32 +-- tests/cases/Misc/TestDate.php | 4 - tests/cases/Misc/TestURL.php | 3 - tests/cases/Misc/TestValueInfo.php | 3 - tests/cases/REST/Fever/TestAPI.php | 169 +++++++--------- tests/cases/REST/Fever/TestUser.php | 6 +- tests/cases/REST/Miniflux/TestToken.php | 6 +- tests/cases/REST/Miniflux/TestV1.php | 6 +- tests/cases/REST/NextcloudNews/TestV1_2.php | 6 +- .../cases/REST/NextcloudNews/TestVersions.php | 2 +- tests/cases/REST/TestREST.php | 51 ++--- tests/cases/REST/TinyTinyRSS/TestIcon.php | 6 +- tests/cases/Service/TestSerial.php | 2 +- tests/cases/Service/TestService.php | 2 +- tests/cases/Service/TestSubprocess.php | 2 +- tests/cases/TestArsse.php | 23 ++- tests/cases/User/TestInternal.php | 2 +- tests/cases/User/TestUser.php | 2 +- tests/lib/AbstractTest.php | 39 ++-- vendor-bin/phpunit/composer.json | 3 +- vendor-bin/phpunit/composer.lock | 149 +++++++++++++- vendor-bin/robo/composer.json | 2 +- vendor-bin/robo/composer.lock | 108 ++++------ 41 files changed, 574 insertions(+), 487 deletions(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index c8f36508..6ecb08aa 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,7 +12,7 @@ const DOCROOT = BASE."tests".DIRECTORY_SEPARATOR."docroot".DIRECTORY_SEPARATOR; ini_set("memory_limit", "-1"); ini_set("zend.assertions", "1"); ini_set("assert.exception", "true"); -error_reporting(\E_ALL); +error_reporting(\E_ALL ^ \E_DEPRECATED); require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php"; if (function_exists("xdebug_set_filter")) { diff --git a/tests/cases/CLI/TestCLI.php b/tests/cases/CLI/TestCLI.php index 5c8e8209..ff62c75e 100644 --- a/tests/cases/CLI/TestCLI.php +++ b/tests/cases/CLI/TestCLI.php @@ -20,13 +20,16 @@ use JKingWeb\Arsse\ImportExport\OPML; /** @covers \JKingWeb\Arsse\CLI */ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { - self::clearData(); - $this->cli = \Phake::partialMock(CLI::class); - \Phake::when($this->cli)->logError->thenReturn(null); - \Phake::when($this->cli)->loadConf->thenReturn(true); + parent::setUp(); + $this->cli = $this->partialMock(CLI::class); + $this->cli->logError->returns(null); + $this->cli->loadConf->returns(true); + $this->dbMock = $this->mock(Database::class); } - public function assertConsole(CLI $cli, string $command, int $exitStatus, string $output = "", bool $pattern = false): void { + public function assertConsole(string $command, int $exitStatus, string $output = "", bool $pattern = false): void { + Arsse::$obj = $this->objMock->get(); + Arsse::$db = $this->dbMock->get(); $argv = \Clue\Arguments\split($command); $output = strlen($output) ? $output.\PHP_EOL : ""; if ($pattern) { @@ -34,18 +37,18 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { } else { $this->expectOutputString($output); } - $this->assertSame($exitStatus, $cli->dispatch($argv)); + $this->assertSame($exitStatus, $this->cli->get()->dispatch($argv)); } public function testPrintVersion(): void { - $this->assertConsole($this->cli, "arsse.php --version", 0, Arsse::VERSION); - \Phake::verify($this->cli, \Phake::times(0))->loadConf; + $this->assertConsole("arsse.php --version", 0, Arsse::VERSION); + $this->cli->loadConf->never()->called(); } /** @dataProvider provideHelpText */ public function testPrintHelp(string $cmd, string $name): void { - $this->assertConsole($this->cli, $cmd, 0, str_replace("arsse.php", $name, CLI::USAGE)); - \Phake::verify($this->cli, \Phake::times(0))->loadConf; + $this->assertConsole($cmd, 0, str_replace("arsse.php", $name, CLI::USAGE)); + $this->cli->loadConf->never()->called(); } public function provideHelpText(): iterable { @@ -60,31 +63,30 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { } public function testStartTheDaemon(): void { - $srv = \Phake::mock(Service::class); - \Phake::when(Arsse::$obj)->get(Service::class)->thenReturn($srv); - \Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable); - $this->assertConsole($this->cli, "arsse.php daemon", 0); - \Phake::verify($this->cli)->loadConf; - \Phake::verify($srv)->watch(true); + $srv = $this->mock(Service::class); + $srv->watch->returns(new \DateTimeImmutable); + $this->objMock->get->with(Service::class)->returns($srv->get()); + $this->assertConsole("arsse.php daemon", 0); + $this->cli->loadConf->called(); + $srv->watch->calledWith(true); } public function testRefreshAllFeeds(): void { - $srv = \Phake::mock(Service::class); - \Phake::when(Arsse::$obj)->get(Service::class)->thenReturn($srv); - \Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable); - $this->assertConsole($this->cli, "arsse.php feed refresh-all", 0); - \Phake::verify($this->cli)->loadConf; - \Phake::verify($srv)->watch(false); + $srv = $this->mock(Service::class); + $srv->watch->returns(new \DateTimeImmutable); + $this->objMock->get->with(Service::class)->returns($srv->get()); + $this->assertConsole("arsse.php feed refresh-all", 0); + $this->cli->loadConf->called(); + $srv->watch->calledWith(false); } /** @dataProvider provideFeedUpdates */ public function testRefreshAFeed(string $cmd, int $exitStatus, string $output): void { - Arsse::$db = \Phake::mock(Database::class); - \Phake::when(Arsse::$db)->feedUpdate(1, true)->thenReturn(true); - \Phake::when(Arsse::$db)->feedUpdate(2, true)->thenThrow(new \JKingWeb\Arsse\Feed\Exception("", ['url' => "http://example.com/"], $this->mockGuzzleException(ClientException::class, "", 404))); - $this->assertConsole($this->cli, $cmd, $exitStatus, $output); - \Phake::verify($this->cli)->loadConf; - \Phake::verify(Arsse::$db)->feedUpdate; + $this->dbMock->feedUpdate->with(1, true)->returns(true); + $this->dbMock->feedUpdate->with(2, true)->throws(new \JKingWeb\Arsse\Feed\Exception("", ['url' => "http://example.com/"], $this->mockGuzzleException(ClientException::class, "", 404))); + $this->assertConsole($cmd, $exitStatus, $output); + $this->cli->loadConf->called(); + $this->dbMock->feedUpdate->called(); } public function provideFeedUpdates(): iterable { @@ -96,14 +98,14 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideDefaultConfigurationSaves */ public function testSaveTheDefaultConfiguration(string $cmd, int $exitStatus, string $file): void { - $conf = \Phake::mock(Conf::class); - \Phake::when(Arsse::$obj)->get(Conf::class)->thenReturn($conf); - \Phake::when($conf)->exportFile("php://output", true)->thenReturn(true); - \Phake::when($conf)->exportFile("good.conf", true)->thenReturn(true); - \Phake::when($conf)->exportFile("bad.conf", true)->thenThrow(new \JKingWeb\Arsse\Conf\Exception("fileUnwritable")); - $this->assertConsole($this->cli, $cmd, $exitStatus); - \Phake::verify($this->cli, \Phake::times(0))->loadConf; - \Phake::verify($conf)->exportFile($file, true); + $conf = $this->mock(Conf::class); + $conf->exportFile->with("php://output", true)->returns(true); + $conf->exportFile->with("good.conf", true)->returns(true); + $conf->exportFile->with("bad.conf", true)->throws(new \JKingWeb\Arsse\Conf\Exception("fileUnwritable")); + $this->objMock->get->with(Conf::class)->returns($conf->get()); + $this->assertConsole($cmd, $exitStatus); + $this->cli->loadConf->never()->called(); + $conf->exportFile->calledWith($file, true); } public function provideDefaultConfigurationSaves(): iterable { @@ -120,7 +122,7 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { // FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead Arsse::$user = $this->createMock(User::class); Arsse::$user->method("list")->willReturn($list); - $this->assertConsole($this->cli, $cmd, $exitStatus, $output); + $this->assertConsole($cmd, $exitStatus, $output); } public function provideUserList(): iterable { @@ -146,7 +148,7 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { return is_null($pass) ? "random password" : $pass; } })); - $this->assertConsole($this->cli, $cmd, $exitStatus, $output); + $this->assertConsole($cmd, $exitStatus, $output); } public function provideUserAdditions(): iterable { @@ -163,7 +165,7 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { Arsse::$user->method("propertiesSet")->willReturn([]); Arsse::$user->expects($this->exactly(1))->method("add")->with("jane.doe@example.com", null); Arsse::$user->expects($this->exactly(1))->method("propertiesSet")->with("jane.doe@example.com", ['admin' => true]); - $this->assertConsole($this->cli, "arsse.php user add jane.doe@example.com --admin", 0, "random password"); + $this->assertConsole("arsse.php user add jane.doe@example.com --admin", 0, "random password"); } /** @dataProvider provideUserAuthentication */ @@ -176,12 +178,12 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { ($user === "jane.doe@example.com" && $pass === "superman") ; })); - $fever = \Phake::mock(FeverUser::class); - \Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever); - \Phake::when($fever)->authenticate->thenReturn(false); - \Phake::when($fever)->authenticate("john.doe@example.com", "ashalla")->thenReturn(true); - \Phake::when($fever)->authenticate("jane.doe@example.com", "thx1138")->thenReturn(true); - $this->assertConsole($this->cli, $cmd, $exitStatus, $output); + $fever = $this->mock(FeverUser::class); + $fever->authenticate->returns(false); + $fever->authenticate->with("john.doe@example.com", "ashalla")->returns(true); + $fever->authenticate->with("jane.doe@example.com", "thx1138")->returns(true); + $this->objMock->get->with(FeverUser::class)->returns($fever->get()); + $this->assertConsole($cmd, $exitStatus, $output); } public function provideUserAuthentication(): iterable { @@ -210,7 +212,7 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { } throw new \JKingWeb\Arsse\User\ExceptionConflict("doesNotExist"); })); - $this->assertConsole($this->cli, $cmd, $exitStatus, $output); + $this->assertConsole($cmd, $exitStatus, $output); } public function provideUserRemovals(): iterable { @@ -233,10 +235,10 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { // FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead Arsse::$user = $this->createMock(User::class); Arsse::$user->method("passwordSet")->will($this->returnCallback($passwordChange)); - $fever = \Phake::mock(FeverUser::class); - \Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever); - \Phake::when($fever)->register->thenReturnCallback($passwordChange); - $this->assertConsole($this->cli, $cmd, $exitStatus, $output); + $fever = $this->mock(FeverUser::class); + $fever->register->does($passwordChange); + $this->objMock->get->with(FeverUser::class)->returns($fever->get()); + $this->assertConsole($cmd, $exitStatus, $output); } public function provideUserPasswordChanges(): iterable { @@ -263,10 +265,10 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { // FIXME: Phake is somehow unable to mock the User class correctly, so we use PHPUnit's mocks instead Arsse::$user = $this->createMock(User::class); Arsse::$user->method("passwordUnset")->will($this->returnCallback($passwordClear)); - $fever = \Phake::mock(FeverUser::class); - \Phake::when(Arsse::$obj)->get(FeverUser::class)->thenReturn($fever); - \Phake::when($fever)->unregister->thenReturnCallback($passwordClear); - $this->assertConsole($this->cli, $cmd, $exitStatus, $output); + $fever = $this->mock(FeverUser::class); + $fever->unregister->does($passwordClear); + $this->objMock->get->with(FeverUser::class)->returns($fever->get()); + $this->assertConsole($cmd, $exitStatus, $output); } public function provideUserPasswordClearings(): iterable { @@ -280,14 +282,14 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideOpmlExports */ public function testExportToOpml(string $cmd, int $exitStatus, string $file, string $user, bool $flat): void { - $opml = \Phake::mock(OPML::class); - \Phake::when(Arsse::$obj)->get(OPML::class)->thenReturn($opml); - \Phake::when($opml)->exportFile("php://output", $user, $flat)->thenReturn(true); - \Phake::when($opml)->exportFile("good.opml", $user, $flat)->thenReturn(true); - \Phake::when($opml)->exportFile("bad.opml", $user, $flat)->thenThrow(new \JKingWeb\Arsse\ImportExport\Exception("fileUnwritable")); - $this->assertConsole($this->cli, $cmd, $exitStatus); - \Phake::verify($this->cli)->loadConf; - \Phake::verify($opml)->exportFile($file, $user, $flat); + $opml = $this->mock(OPML::class); + $opml->exportFile->with("php://output", $user, $flat)->returns(true); + $opml->exportFile->with("good.opml", $user, $flat)->returns(true); + $opml->exportFile->with("bad.opml", $user, $flat)->throws(new \JKingWeb\Arsse\ImportExport\Exception("fileUnwritable")); + $this->objMock->get->with(OPML::class)->returns($opml->get()); + $this->assertConsole($cmd, $exitStatus); + $this->cli->loadConf->called(); + $opml->exportFile->calledWith($file, $user, $flat); } public function provideOpmlExports(): iterable { @@ -321,14 +323,14 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideOpmlImports */ public function testImportFromOpml(string $cmd, int $exitStatus, string $file, string $user, bool $flat, bool $replace): void { - $opml = \Phake::mock(OPML::class); - \Phake::when(Arsse::$obj)->get(OPML::class)->thenReturn($opml); - \Phake::when($opml)->importFile("php://input", $user, $flat, $replace)->thenReturn(true); - \Phake::when($opml)->importFile("good.opml", $user, $flat, $replace)->thenReturn(true); - \Phake::when($opml)->importFile("bad.opml", $user, $flat, $replace)->thenThrow(new \JKingWeb\Arsse\ImportExport\Exception("fileUnreadable")); - $this->assertConsole($this->cli, $cmd, $exitStatus); - \Phake::verify($this->cli)->loadConf; - \Phake::verify($opml)->importFile($file, $user, $flat, $replace); + $opml = $this->mock(OPML::class); + $opml->importFile->with("php://input", $user, $flat, $replace)->returns(true); + $opml->importFile->with("good.opml", $user, $flat, $replace)->returns(true); + $opml->importFile->with("bad.opml", $user, $flat, $replace)->throws(new \JKingWeb\Arsse\ImportExport\Exception("fileUnreadable")); + $this->objMock->get->with(OPML::class)->returns($opml->get()); + $this->assertConsole($cmd, $exitStatus); + $this->cli->loadConf->called(); + $opml->importFile->calledWith($file, $user, $flat, $replace); } public function provideOpmlImports(): iterable { @@ -400,7 +402,7 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { Arsse::$user = $this->createMock(User::class); Arsse::$user->method("propertiesGet")->willReturn($data); Arsse::$user->expects($this->once())->method("propertiesGet")->with("john.doe@example.com", true); - $this->assertConsole($this->cli, "arsse.php user show john.doe@example.com", 0, $exp); + $this->assertConsole("arsse.php user show john.doe@example.com", 0, $exp); } /** @dataProvider provideMetadataChanges */ @@ -408,7 +410,7 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { Arsse::$user = $this->createMock(User::class); Arsse::$user->method("propertiesSet")->willReturn($out); Arsse::$user->expects($this->once())->method("propertiesSet")->with($user, $in); - $this->assertConsole($this->cli, $cmd, $exp, ""); + $this->assertConsole($cmd, $exp, ""); } public function provideMetadataChanges(): iterable { @@ -433,40 +435,38 @@ class TestCLI extends \JKingWeb\Arsse\Test\AbstractTest { "TOKEN 2 Eek", "TOKEN 1 Ook", ]); - $t = \Phake::mock(MinifluxToken::class); - \Phake::when(Arsse::$obj)->get(MinifluxToken::class)->thenReturn($t); - \Phake::when($t)->tokenList->thenReturn($data); - $this->assertConsole($this->cli, "arsse.php token list john", 0, $exp); - \Phake::verify($t)->tokenList("john"); + $t = $this->mock(MinifluxToken::class); + $t->tokenList->returns($data); + $this->objMock->get->with(MinifluxToken::class)->returns($t->get()); + $this->assertConsole("arsse.php token list john", 0, $exp); + $t->tokenList->calledWith("john"); } public function testCreateToken(): void { - $t = \Phake::mock(MinifluxToken::class); - \Phake::when(Arsse::$obj)->get(MinifluxToken::class)->thenReturn($t); - \Phake::when($t)->tokenGenerate->thenReturn("RANDOM TOKEN"); - $this->assertConsole($this->cli, "arse.php token create jane", 0, "RANDOM TOKEN"); - \Phake::verify($t)->tokenGenerate("jane", null); + $t = $this->mock(MinifluxToken::class); + $t->tokenGenerate->returns("RANDOM TOKEN"); + $this->objMock->get->with(MinifluxToken::class)->returns($t->get()); + $this->assertConsole("arse.php token create jane", 0, "RANDOM TOKEN"); + $t->tokenGenerate->calledWith("jane", null); } public function testCreateTokenWithLabel(): void { - $t = \Phake::mock(MinifluxToken::class); - \Phake::when(Arsse::$obj)->get(MinifluxToken::class)->thenReturn($t); - \Phake::when($t)->tokenGenerate->thenReturn("RANDOM TOKEN"); - $this->assertConsole($this->cli, "arse.php token create jane Ook", 0, "RANDOM TOKEN"); - \Phake::verify($t)->tokenGenerate("jane", "Ook"); + $t = $this->mock(MinifluxToken::class); + $t->tokenGenerate->returns("RANDOM TOKEN"); + $this->objMock->get->with(MinifluxToken::class)->returns($t->get()); + $this->assertConsole("arse.php token create jane Ook", 0, "RANDOM TOKEN"); + $t->tokenGenerate->calledWith("jane", "Ook"); } public function testRevokeAToken(): void { - Arsse::$db = \Phake::mock(Database::class); - \Phake::when(Arsse::$db)->tokenRevoke->thenReturn(true); - $this->assertConsole($this->cli, "arse.php token revoke jane TOKEN_ID", 0); - \Phake::verify(Arsse::$db)->tokenRevoke("jane", "miniflux.login", "TOKEN_ID"); + $this->dbMock->tokenRevoke->returns(true); + $this->assertConsole("arse.php token revoke jane TOKEN_ID", 0); + $this->dbMock->tokenRevoke->calledWith("jane", "miniflux.login", "TOKEN_ID"); } public function testRevokeAllTokens(): void { - Arsse::$db = \Phake::mock(Database::class); - \Phake::when(Arsse::$db)->tokenRevoke->thenReturn(true); - $this->assertConsole($this->cli, "arse.php token revoke jane", 0); - \Phake::verify(Arsse::$db)->tokenRevoke("jane", "miniflux.login", null); + $this->dbMock->tokenRevoke->returns(true); + $this->assertConsole("arse.php token revoke jane", 0); + $this->dbMock->tokenRevoke->calledWith("jane", "miniflux.login", null); } } diff --git a/tests/cases/Conf/TestConf.php b/tests/cases/Conf/TestConf.php index e99eda3e..088746bb 100644 --- a/tests/cases/Conf/TestConf.php +++ b/tests/cases/Conf/TestConf.php @@ -15,7 +15,7 @@ class TestConf extends \JKingWeb\Arsse\Test\AbstractTest { public static $path; public function setUp(): void { - self::clearData(); + parent::setUp(); self::$vfs = vfsStream::setup("root", null, [ 'confGood' => ' "xx");', 'confNotArray' => 'driverSchemaUpdate(); // create a mock user manager - Arsse::$user = \Phake::mock(User::class); + $this->userMock = $this->mock(User::class); + Arsse::$user = $this->userMock->get(); // call the series-specific setup method $setUp = "setUp".$this->series; $this->$setUp(); diff --git a/tests/cases/Database/SeriesSubscription.php b/tests/cases/Database/SeriesSubscription.php index f235a916..b029846b 100644 --- a/tests/cases/Database/SeriesSubscription.php +++ b/tests/cases/Database/SeriesSubscription.php @@ -192,8 +192,6 @@ trait SeriesSubscription { ], ], ]; - // initialize a partial mock of the Database object to later manipulate the feedUpdate method - Arsse::$db = \Phake::partialMock(Database::class, static::$drv); $this->user = "john.doe@example.com"; } @@ -204,9 +202,11 @@ trait SeriesSubscription { public function testAddASubscriptionToAnExistingFeed(): void { $url = "http://example.com/feed1"; $subID = $this->nextID("arsse_subscriptions"); - \Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); + $db = $this->partialMock(Database::class, static::$drv); + $db->feedUpdate->returns(true); + Arsse::$db = $db->get(); $this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url)); - \Phake::verify(Arsse::$db, \Phake::times(0))->feedUpdate(1, true); + $db->feedUpdate->never()->called(); $state = $this->primeExpectations($this->data, [ 'arsse_feeds' => ['id','url','username','password'], 'arsse_subscriptions' => ['id','owner','feed'], @@ -219,9 +219,11 @@ trait SeriesSubscription { $url = "http://example.org/feed1"; $feedID = $this->nextID("arsse_feeds"); $subID = $this->nextID("arsse_subscriptions"); - \Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); + $db = $this->partialMock(Database::class, static::$drv); + $db->feedUpdate->returns(true); + Arsse::$db = $db->get(); $this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", false)); - \Phake::verify(Arsse::$db)->feedUpdate($feedID, true, false); + $db->feedUpdate->calledWith($feedID, true, false); $state = $this->primeExpectations($this->data, [ 'arsse_feeds' => ['id','url','username','password'], 'arsse_subscriptions' => ['id','owner','feed'], @@ -236,9 +238,11 @@ trait SeriesSubscription { $discovered = "http://localhost:8000/Feed/Discovery/Feed"; $feedID = $this->nextID("arsse_feeds"); $subID = $this->nextID("arsse_subscriptions"); - \Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); + $db = $this->partialMock(Database::class, static::$drv); + $db->feedUpdate->returns(true); + Arsse::$db = $db->get(); $this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", true)); - \Phake::verify(Arsse::$db)->feedUpdate($feedID, true, false); + $db->feedUpdate->calledWith($feedID, true, false); $state = $this->primeExpectations($this->data, [ 'arsse_feeds' => ['id','url','username','password'], 'arsse_subscriptions' => ['id','owner','feed'], @@ -251,12 +255,14 @@ trait SeriesSubscription { public function testAddASubscriptionToAnInvalidFeed(): void { $url = "http://example.org/feed1"; $feedID = $this->nextID("arsse_feeds"); - \Phake::when(Arsse::$db)->feedUpdate->thenThrow(new FeedException("", ['url' => $url], $this->mockGuzzleException(ClientException::class, "", 404))); + $db = $this->partialMock(Database::class, static::$drv); + $db->feedUpdate->throws(new FeedException("", ['url' => $url], $this->mockGuzzleException(ClientException::class, "", 404))); + Arsse::$db = $db->get(); $this->assertException("invalidUrl", "Feed"); try { Arsse::$db->subscriptionAdd($this->user, $url, "", "", false); } finally { - \Phake::verify(Arsse::$db)->feedUpdate($feedID, true, false); + $db->feedUpdate->calledWith($feedID, true, false); $state = $this->primeExpectations($this->data, [ 'arsse_feeds' => ['id','url','username','password'], 'arsse_subscriptions' => ['id','owner','feed'], diff --git a/tests/cases/Database/TestDatabase.php b/tests/cases/Database/TestDatabase.php index cfaed762..00838b3a 100644 --- a/tests/cases/Database/TestDatabase.php +++ b/tests/cases/Database/TestDatabase.php @@ -13,10 +13,10 @@ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { protected $db = null; public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); try { - $this->db = \Phake::makeVisible(\Phake::partialMock(Database::class)); + $this->db = new Database; } catch (\JKingWeb\Arsse\Db\Exception $e) { $this->markTestSkipped("SQLite 3 database driver not available"); } @@ -24,14 +24,20 @@ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { public function tearDown(): void { $this->db = null; - self::clearData(); + parent::tearDown(); + } + + protected function invoke(string $method, ...$arg) { + $m = new \ReflectionMethod($this->db, $method); + $m->setAccessible(true); + return $m->invoke($this->db, ...$arg); } /** @dataProvider provideInClauses */ public function testGenerateInClause(string $clause, array $values, array $inV, string $inT): void { $types = array_fill(0, sizeof($values), $inT); $exp = [$clause, $types, $values]; - $this->assertSame($exp, $this->db->generateIn($inV, $inT)); + $this->assertSame($exp, $this->invoke("generateIn", $inV, $inT)); } public function provideInClauses(): iterable { @@ -66,7 +72,7 @@ class TestDatabase extends \JKingWeb\Arsse\Test\AbstractTest { // this is not an exhaustive test; integration tests already cover the ins and outs of the functionality $types = array_fill(0, sizeof($values), "str"); $exp = [$clause, $types, $values]; - $this->assertSame($exp, $this->db->generateSearch($inV, $inC, $inAny)); + $this->assertSame($exp, $this->invoke("generateSearch", $inV, $inC, $inAny)); } public function provideSearchClauses(): iterable { diff --git a/tests/cases/Db/BaseDriver.php b/tests/cases/Db/BaseDriver.php index e34cf65f..89a26007 100644 --- a/tests/cases/Db/BaseDriver.php +++ b/tests/cases/Db/BaseDriver.php @@ -31,7 +31,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { } public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(static::$conf); if (!static::$interface) { $this->markTestSkipped(static::$implementation." database driver not available"); @@ -48,7 +48,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { public function tearDown(): void { // deconstruct the driver unset($this->drv); - self::clearData(); + parent::tearDown(); } public static function tearDownAfterClass(): void { @@ -57,7 +57,7 @@ abstract class BaseDriver extends \JKingWeb\Arsse\Test\AbstractTest { static::dbRaze(static::$interface); } static::$interface = null; - self::clearData(); + self::clearData(true); } protected function exec($q): bool { diff --git a/tests/cases/Db/BaseResult.php b/tests/cases/Db/BaseResult.php index e848f51b..3cfc5bb7 100644 --- a/tests/cases/Db/BaseResult.php +++ b/tests/cases/Db/BaseResult.php @@ -25,7 +25,7 @@ abstract class BaseResult extends \JKingWeb\Arsse\Test\AbstractTest { } public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); if (!static::$interface) { $this->markTestSkipped(static::$implementation." database driver not available"); @@ -35,17 +35,13 @@ abstract class BaseResult extends \JKingWeb\Arsse\Test\AbstractTest { $this->resultClass = static::$dbResultClass; } - public function tearDown(): void { - self::clearData(); - } - public static function tearDownAfterClass(): void { if (static::$interface) { // completely clear the database static::dbRaze(static::$interface); } static::$interface = null; - self::clearData(); + self::clearData(true); } public function testConstructResult(): void { diff --git a/tests/cases/Db/BaseStatement.php b/tests/cases/Db/BaseStatement.php index ba862693..bb8630e7 100644 --- a/tests/cases/Db/BaseStatement.php +++ b/tests/cases/Db/BaseStatement.php @@ -23,7 +23,7 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest { } public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); if (!static::$interface) { $this->markTestSkipped(static::$implementation." database driver not available"); @@ -33,17 +33,13 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest { $this->statementClass = static::$dbStatementClass; } - public function tearDown(): void { - self::clearData(); - } - public static function tearDownAfterClass(): void { if (static::$interface) { // completely clear the database static::dbRaze(static::$interface); } static::$interface = null; - self::clearData(); + self::clearData(true); } public function testConstructStatement(): void { diff --git a/tests/cases/Db/BaseUpdate.php b/tests/cases/Db/BaseUpdate.php index 4e1ed79b..c2a7cc18 100644 --- a/tests/cases/Db/BaseUpdate.php +++ b/tests/cases/Db/BaseUpdate.php @@ -29,7 +29,7 @@ class BaseUpdate extends \JKingWeb\Arsse\Test\AbstractTest { if (!static::$interface) { $this->markTestSkipped(static::$implementation." database driver not available"); } - self::clearData(); + parent::setUp(); self::setConf(); // construct a fresh driver for each test $this->drv = new static::$dbDriverClass; @@ -46,7 +46,7 @@ class BaseUpdate extends \JKingWeb\Arsse\Test\AbstractTest { // deconstruct the driver unset($this->drv); unset($this->path, $this->base, $this->vfs); - self::clearData(); + parent::tearDown(); } public static function tearDownAfterClass(): void { @@ -55,7 +55,7 @@ class BaseUpdate extends \JKingWeb\Arsse\Test\AbstractTest { static::dbRaze(static::$interface); } static::$interface = null; - self::clearData(); + self::clearData(true); } public function testLoadMissingFile(): void { diff --git a/tests/cases/Db/SQLite3/TestCreation.php b/tests/cases/Db/SQLite3/TestCreation.php index 1a4eef91..3e3b2f29 100644 --- a/tests/cases/Db/SQLite3/TestCreation.php +++ b/tests/cases/Db/SQLite3/TestCreation.php @@ -22,7 +22,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { if (!Driver::requirementsMet()) { $this->markTestSkipped("SQLite extension not loaded"); } - self::clearData(); + parent::setUp(); // test files $this->files = [ // cannot create files @@ -108,10 +108,6 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { self::setConf(); } - public function tearDown(): void { - self::clearData(); - } - public function testFailToCreateDatabase(): void { Arsse::$conf->dbSQLite3File = $this->path."Cmain/arsse.db"; $this->assertException("fileUncreatable", "Db"); diff --git a/tests/cases/Db/SQLite3PDO/TestCreation.php b/tests/cases/Db/SQLite3PDO/TestCreation.php index 3b28cd50..ea5e9a32 100644 --- a/tests/cases/Db/SQLite3PDO/TestCreation.php +++ b/tests/cases/Db/SQLite3PDO/TestCreation.php @@ -24,7 +24,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { if (!Driver::requirementsMet()) { $this->markTestSkipped("PDO-SQLite extension not loaded"); } - self::clearData(); + parent::setUp(); // test files $this->files = [ // cannot create files @@ -110,10 +110,6 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { self::setConf(); } - public function tearDown(): void { - self::clearData(); - } - public function testFailToCreateDatabase(): void { Arsse::$conf->dbSQLite3File = $this->path."Cmain/arsse.db"; $this->assertException("fileUncreatable", "Db"); diff --git a/tests/cases/Db/TestTransaction.php b/tests/cases/Db/TestTransaction.php index 6b8aed58..6a850509 100644 --- a/tests/cases/Db/TestTransaction.php +++ b/tests/cases/Db/TestTransaction.php @@ -15,47 +15,50 @@ class TestTransaction extends \JKingWeb\Arsse\Test\AbstractTest { protected $drv; public function setUp(): void { - self::clearData(); - $drv = \Phake::mock(\JKingWeb\Arsse\Db\SQLite3\Driver::class); - \Phake::when($drv)->savepointRelease->thenReturn(true); - \Phake::when($drv)->savepointUndo->thenReturn(true); - \Phake::when($drv)->savepointCreate->thenReturn(1)->thenReturn(2); + parent::setUp(); + $drv = $this->mock(\JKingWeb\Arsse\Db\SQLite3\Driver::class); + $drv->savepointRelease->returns(true); + $drv->savepointUndo->returns(true); + $drv->savepointCreate->returns(1, 2); $this->drv = $drv; } public function testManipulateTransactions(): void { - $tr1 = new Transaction($this->drv); - $tr2 = new Transaction($this->drv); - \Phake::verify($this->drv, \Phake::times(2))->savepointCreate; + $drv = $this->drv->get(); + $tr1 = new Transaction($drv); + $tr2 = new Transaction($drv); + $this->drv->savepointCreate->twice()->called(); $this->assertSame(1, $tr1->getIndex()); $this->assertSame(2, $tr2->getIndex()); unset($tr1); - \Phake::verify($this->drv)->savepointUndo(1); + $this->drv->savepointUndo->calledWith(1); unset($tr2); - \Phake::verify($this->drv)->savepointUndo(2); + $this->drv->savepointUndo->calledWith(2); } public function testCloseTransactions(): void { - $tr1 = new Transaction($this->drv); - $tr2 = new Transaction($this->drv); + $drv = $this->drv->get(); + $tr1 = new Transaction($drv); + $tr2 = new Transaction($drv); $this->assertTrue($tr1->isPending()); $this->assertTrue($tr2->isPending()); $tr1->commit(); $this->assertFalse($tr1->isPending()); $this->assertTrue($tr2->isPending()); - \Phake::verify($this->drv)->savepointRelease(1); + $this->drv->savepointRelease->calledWith(1); $tr2->rollback(); $this->assertFalse($tr1->isPending()); $this->assertFalse($tr2->isPending()); - \Phake::verify($this->drv)->savepointUndo(2); + $this->drv->savepointUndo->calledWith(2); } public function testIgnoreRollbackErrors(): void { - \Phake::when($this->drv)->savepointUndo->thenThrow(new Exception("savepointStale")); - $tr1 = new Transaction($this->drv); - $tr2 = new Transaction($this->drv); + $this->drv->savepointUndo->throws(new Exception("savepointStale")); + $drv = $this->drv->get(); + $tr1 = new Transaction($drv); + $tr2 = new Transaction($drv); unset($tr1, $tr2); // no exception should bubble up - \Phake::verify($this->drv)->savepointUndo(1); - \Phake::verify($this->drv)->savepointUndo(2); + $this->drv->savepointUndo->calledWith(1); + $this->drv->savepointUndo->calledWith(2); } } diff --git a/tests/cases/Exception/TestException.php b/tests/cases/Exception/TestException.php index 563a4f58..c85bff8d 100644 --- a/tests/cases/Exception/TestException.php +++ b/tests/cases/Exception/TestException.php @@ -16,16 +16,9 @@ class TestException extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { self::clearData(false); // create a mock Lang object so as not to create a dependency loop - Arsse::$lang = \Phake::mock(Lang::class); - \Phake::when(Arsse::$lang)->msg->thenReturn(""); - } - - public function tearDown(): void { - // verify calls to the mock Lang object - \Phake::verify(Arsse::$lang, \Phake::atLeast(0))->msg($this->isType("string"), $this->anything()); - \Phake::verifyNoOtherInteractions(Arsse::$lang); - // clean up - self::clearData(true); + $this->langMock = $this->mock(Lang::class); + $this->langMock->msg->returns(""); + Arsse::$lang = $this->langMock->get(); } public function testBaseClass(): void { diff --git a/tests/cases/Feed/TestFeed.php b/tests/cases/Feed/TestFeed.php index cdfcec1e..857c42e7 100644 --- a/tests/cases/Feed/TestFeed.php +++ b/tests/cases/Feed/TestFeed.php @@ -11,6 +11,7 @@ use JKingWeb\Arsse\Feed; use JKingWeb\Arsse\Database; use JKingWeb\Arsse\Misc\Date; use JKingWeb\Arsse\Test\Result; +use Eloquent\Phony\Phpunit\Phony; /** * @covers \JKingWeb\Arsse\Feed @@ -92,12 +93,15 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { $this->markTestSkipped("Test Web server is not accepting requests"); } $this->base = self::$host."Feed/"; - self::clearData(); + parent::setUp(); self::setConf(); - Arsse::$db = \Phake::mock(Database::class); - \Phake::when(Arsse::$db)->feedMatchLatest->thenReturn(new Result([])); - \Phake::when(Arsse::$db)->feedMatchIds->thenReturn(new Result([])); - \Phake::when(Arsse::$db)->feedRulesGet->thenReturn([]); + $this->dbMock = $this->mock(Database::class); + $this->dbMock->feedMatchLatest->with(Phony::wildcard())->returns(new Result([])); + $this->dbMock->feedMatchLatest->with(1, Phony::any())->returns(new Result($this->latest)); + $this->dbMock->feedMatchIds->with(Phony::wildcard())->returns(new Result([])); + $this->dbMock->feedMatchIds->with(1, Phony::wildcard())->returns(new Result($this->others)); + $this->dbMock->feedRulesGet->returns([]); + Arsse::$db = $this->dbMock->get(); } public function testParseAFeed(): void { @@ -338,7 +342,10 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { } public function testMatchLatestArticles(): void { - \Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Result($this->latest)); + $this->dbMock = $this->mock(Database::class); + $this->dbMock->feedMatchLatest->with(Phony::wildcard())->returns(new Result([])); + $this->dbMock->feedMatchLatest->with(1, Phony::any())->returns(new Result($this->latest)); + Arsse::$db = $this->dbMock->get(); $f = new Feed(1, $this->base."Matching/1"); $this->assertCount(0, $f->newItems); $this->assertCount(0, $f->changedItems); @@ -354,8 +361,6 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { } public function testMatchHistoricalArticles(): void { - \Phake::when(Arsse::$db)->feedMatchLatest(1, $this->anything())->thenReturn(new Result($this->latest)); - \Phake::when(Arsse::$db)->feedMatchIds(1, $this->anything(), $this->anything(), $this->anything(), $this->anything())->thenReturn(new Result($this->others)); $f = new Feed(1, $this->base."Matching/5"); $this->assertCount(0, $f->newItems); $this->assertCount(0, $f->changedItems); @@ -383,7 +388,11 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { } public function testApplyFilterRules(): void { - \Phake::when(Arsse::$db)->feedMatchIds->thenReturn(new Result([ + $exp = [ + 'jack' => ['new' => [false, true, true, false, true], 'changed' => [7 => true, 47 => true, 2112 => false, 1 => true, 42 => false]], + 'sam' => ['new' => [false, true, false, false, false], 'changed' => [7 => false, 47 => true, 2112 => false, 1 => false, 42 => false]], + ]; + $this->dbMock->feedMatchIds->returns(new Result([ // these are the sixth through tenth entries in the feed; the title hashes have been omitted for brevity ['id' => 7, 'guid' => '0f2a218c311e3d8105f1b075142a5d26dabf056ffc61abe77e96c8f071bbf4a7', 'edited' => null, 'url_title_hash' => "", 'url_content_hash' => '', 'title_content_hash' => ''], ['id' => 47, 'guid' => '1c19e3b9018bc246b7414ae919ddebc88d0c575129e8c4a57b84b826c00f6db5', 'edited' => null, 'url_title_hash' => "", 'url_content_hash' => '', 'title_content_hash' => ''], @@ -391,15 +400,12 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { ['id' => 1, 'guid' => '436070cda5713a0d9a8fdc8652c7ab142f0550697acfd5206a16c18aee355039', 'edited' => null, 'url_title_hash' => "", 'url_content_hash' => '', 'title_content_hash' => ''], ['id' => 42, 'guid' => '1a731433a1904220ef26e731ada7262e1d5bcecae53e7b5df9e1f5713af6e5d3', 'edited' => null, 'url_title_hash' => "", 'url_content_hash' => '', 'title_content_hash' => ''], ])); - \Phake::when(Arsse::$db)->feedRulesGet->thenReturn([ + $this->dbMock->feedRulesGet->returns([ 'jack' => ['keep' => "", 'block' => '`A|W|J|S`u'], 'sam' => ['keep' => "`B|T|X`u", 'block' => '`C`u'], ]); + Arsse::$db = $this->dbMock->get(); $f = new Feed(5, $this->base."Filtering/1"); - $exp = [ - 'jack' => ['new' => [false, true, true, false, true], 'changed' => [7 => true, 47 => true, 2112 => false, 1 => true, 42 => false]], - 'sam' => ['new' => [false, true, false, false, false], 'changed' => [7 => false, 47 => true, 2112 => false, 1 => false, 42 => false]], - ]; $this->assertSame($exp, $f->filteredItems); } } diff --git a/tests/cases/Feed/TestFetching.php b/tests/cases/Feed/TestFetching.php index 3ce3e8d2..011aab28 100644 --- a/tests/cases/Feed/TestFetching.php +++ b/tests/cases/Feed/TestFetching.php @@ -23,7 +23,7 @@ class TestFetching extends \JKingWeb\Arsse\Test\AbstractTest { $this->markTestSkipped("Test Web server is not accepting requests"); } $this->base = self::$host."Feed/"; - self::clearData(); + parent::setUp(); self::setConf(); } diff --git a/tests/cases/ImportExport/TestFile.php b/tests/cases/ImportExport/TestFile.php index bbffca67..b5599cbd 100644 --- a/tests/cases/ImportExport/TestFile.php +++ b/tests/cases/ImportExport/TestFile.php @@ -17,11 +17,11 @@ class TestFile extends \JKingWeb\Arsse\Test\AbstractTest { protected $proc; public function setUp(): void { - self::clearData(); + parent::setUp(); // create a mock Import/Export processor with stubbed underlying import/export routines - $this->proc = \Phake::partialMock(AbstractImportExport::class); - \Phake::when($this->proc)->export->thenReturn("EXPORT_FILE"); - \Phake::when($this->proc)->import->thenReturn(true); + $this->proc = $this->partialMock(AbstractImportExport::class); + $this->proc->export->returns("EXPORT_FILE"); + $this->proc->import->returns(true); $this->vfs = vfsStream::setup("root", null, [ 'exportGoodFile' => "", 'exportGoodDir' => [], @@ -41,7 +41,7 @@ class TestFile extends \JKingWeb\Arsse\Test\AbstractTest { $this->path = null; $this->vfs = null; $this->proc = null; - self::clearData(); + parent::tearDown(); } /** @dataProvider provideFileExports */ @@ -50,13 +50,13 @@ class TestFile extends \JKingWeb\Arsse\Test\AbstractTest { try { if ($exp instanceof \JKingWeb\Arsse\AbstractException) { $this->assertException($exp); - $this->proc->exportFile($path, $user, $flat); + $this->proc->get()->exportFile($path, $user, $flat); } else { - $this->assertSame($exp, $this->proc->exportFile($path, $user, $flat)); + $this->assertSame($exp, $this->proc->get()->exportFile($path, $user, $flat)); $this->assertSame("EXPORT_FILE", $this->vfs->getChild($file)->getContent()); } } finally { - \Phake::verify($this->proc)->export($user, $flat); + $this->proc->export->calledWith($user, $flat); } } @@ -89,12 +89,12 @@ class TestFile extends \JKingWeb\Arsse\Test\AbstractTest { try { if ($exp instanceof \JKingWeb\Arsse\AbstractException) { $this->assertException($exp); - $this->proc->importFile($path, $user, $flat, $replace); + $this->proc->get()->importFile($path, $user, $flat, $replace); } else { - $this->assertSame($exp, $this->proc->importFile($path, $user, $flat, $replace)); + $this->assertSame($exp, $this->proc->get()->importFile($path, $user, $flat, $replace)); } } finally { - \Phake::verify($this->proc, \Phake::times((int) ($exp === true)))->import($user, "GOOD_FILE", $flat, $replace); + $this->proc->import->times((int) ($exp === true))->calledWith($user, "GOOD_FILE", $flat, $replace); } } diff --git a/tests/cases/ImportExport/TestImportExport.php b/tests/cases/ImportExport/TestImportExport.php index e113d83c..ae0c7a4a 100644 --- a/tests/cases/ImportExport/TestImportExport.php +++ b/tests/cases/ImportExport/TestImportExport.php @@ -24,11 +24,11 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ]; public function setUp(): void { - self::clearData(); + parent::setUp(); // create a mock user manager - Arsse::$user = \Phake::mock(\JKingWeb\Arsse\User::class); + Arsse::$user = $this->mock(\JKingWeb\Arsse\User::class)->get(); // create a mock Import/Export processor - $this->proc = \Phake::partialMock(AbstractImportExport::class); + $this->proc = $this->partialMock(AbstractImportExport::class); // initialize an SQLite memeory database static::setConf(); try { @@ -142,12 +142,12 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { public function tearDown(): void { $this->drv = null; $this->proc = null; - self::clearData(); + parent::tearDown(); } public function testImportForAMissingUser(): void { $this->assertException("doesNotExist", "User", "ExceptionConflict"); - $this->proc->import("no.one@example.com", "", false, false); + $this->proc->get()->import("no.one@example.com", "", false, false); } public function testImportWithInvalidFolder(): void { @@ -155,9 +155,9 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ], [1 => ['id' => 1, 'name' => "", 'parent' => 0], ]]; - \Phake::when($this->proc)->parse->thenReturn($in); + $this->proc->parse->returns($in); $this->assertException("invalidFolderName", "ImportExport"); - $this->proc->import("john.doe@example.com", "", false, false); + $this->proc->get()->import("john.doe@example.com", "", false, false); } public function testImportWithDuplicateFolder(): void { @@ -166,9 +166,9 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ['id' => 1, 'name' => "New", 'parent' => 0], ['id' => 2, 'name' => "New", 'parent' => 0], ]]; - \Phake::when($this->proc)->parse->thenReturn($in); + $this->proc->parse->returns($in); $this->assertException("invalidFolderCopy", "ImportExport"); - $this->proc->import("john.doe@example.com", "", false, false); + $this->proc->get()->import("john.doe@example.com", "", false, false); } public function testMakeNoEffectiveChanges(): void { @@ -187,11 +187,11 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ['id' => 5, 'name' => "Local", 'parent' => 4], ['id' => 6, 'name' => "National", 'parent' => 4], ]]; - \Phake::when($this->proc)->parse->thenReturn($in); + $this->proc->parse->returns($in); $exp = $this->primeExpectations($this->data, $this->checkTables); - $this->proc->import("john.doe@example.com", "", false, false); + $this->proc->get()->import("john.doe@example.com", "", false, false); $this->compareExpectations($this->drv, $exp); - $this->proc->import("john.doe@example.com", "", false, true); + $this->proc->get()->import("john.doe@example.com", "", false, true); $this->compareExpectations($this->drv, $exp); } @@ -212,8 +212,8 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ['id' => 6, 'name' => "National", 'parent' => 4], ['id' => 7, 'name' => "Nature", 'parent' => 0], // new folder ]]; - \Phake::when($this->proc)->parse->thenReturn($in); - $this->proc->import("john.doe@example.com", "", false, true); + $this->proc->parse->returns($in); + $this->proc->get()->import("john.doe@example.com", "", false, true); $exp = $this->primeExpectations($this->data, $this->checkTables); $exp['arsse_subscriptions']['rows'][3] = [4, "john.doe@example.com", null, 4, "CBC"]; $exp['arsse_folders']['rows'][] = [7, "john.doe@example.com", null, "Nature"]; @@ -224,8 +224,8 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { $in = [[ ['url' => "http://localhost:8000/Import/some-feed", 'title' => "Some Feed", 'folder' => 0, 'tags' => ["frequent", "cryptic"]], //one existing tag and one new one ], []]; - \Phake::when($this->proc)->parse->thenReturn($in); - $this->proc->import("john.doe@example.com", "", false, false); + $this->proc->parse->returns($in); + $this->proc->get()->import("john.doe@example.com", "", false, false); $exp = $this->primeExpectations($this->data, $this->checkTables); $exp['arsse_feeds']['rows'][] = [7, "http://localhost:8000/Import/some-feed", "Some feed"]; // author-supplied and user-supplied titles differ $exp['arsse_subscriptions']['rows'][] = [7, "john.doe@example.com", null, 7, "Some Feed"]; @@ -239,9 +239,9 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { $in = [[ ['url' => "http://localhost:8000/Import/some-feed", 'title' => "Some Feed", 'folder' => 0, 'tags' => [""]], ], []]; - \Phake::when($this->proc)->parse->thenReturn($in); + $this->proc->parse->returns($in); $this->assertException("invalidTagName", "ImportExport"); - $this->proc->import("john.doe@example.com", "", false, false); + $this->proc->get()->import("john.doe@example.com", "", false, false); } public function testReplaceData(): void { @@ -250,8 +250,8 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ], [1 => ['id' => 1, 'name' => "Photography", 'parent' => 0], ]]; - \Phake::when($this->proc)->parse->thenReturn($in); - $this->proc->import("john.doe@example.com", "", false, true); + $this->proc->parse->returns($in); + $this->proc->get()->import("john.doe@example.com", "", false, true); $exp = $this->primeExpectations($this->data, $this->checkTables); $exp['arsse_feeds']['rows'][] = [7, "http://localhost:8000/Import/some-feed", "Some feed"]; // author-supplied and user-supplied titles differ $exp['arsse_subscriptions']['rows'] = [[7, "john.doe@example.com", 4, 7, "Some Feed"]]; diff --git a/tests/cases/ImportExport/TestOPML.php b/tests/cases/ImportExport/TestOPML.php index e527db0d..ff21542a 100644 --- a/tests/cases/ImportExport/TestOPML.php +++ b/tests/cases/ImportExport/TestOPML.php @@ -7,9 +7,11 @@ declare(strict_types=1); namespace JKingWeb\Arsse\TestCase\ImportExport; use JKingWeb\Arsse\Arsse; +use JKingWeb\Arsse\Database; use JKingWeb\Arsse\Test\Result; use JKingWeb\Arsse\ImportExport\OPML; use JKingWeb\Arsse\ImportExport\Exception; +use ReflectionMethod; /** @covers \JKingWeb\Arsse\ImportExport\OPML */ class TestOPML extends \JKingWeb\Arsse\Test\AbstractTest { @@ -80,27 +82,25 @@ OPML_EXPORT_SERIALIZATION; OPML_EXPORT_SERIALIZATION; public function setUp(): void { - self::clearData(); - Arsse::$db = \Phake::mock(\JKingWeb\Arsse\Database::class); - \Phake::when(Arsse::$db)->userExists->thenReturn(true); + parent::setUp(); + $this->dbMock = $this->mock(Database::class); + $this->dbMock->userExists->returns(true); + $this->dbMock->folderList->with("john.doe@example.com")->returns(new Result($this->folders)); + $this->dbMock->subscriptionList->with("john.doe@example.com")->returns(new Result($this->subscriptions)); + $this->dbMock->tagSummarize->with("john.doe@example.com")->returns(new Result($this->tags)); + Arsse::$db = $this->dbMock->get(); } public function testExportToOpml(): void { - \Phake::when(Arsse::$db)->folderList("john.doe@example.com")->thenReturn(new Result($this->folders)); - \Phake::when(Arsse::$db)->subscriptionList("john.doe@example.com")->thenReturn(new Result($this->subscriptions)); - \Phake::when(Arsse::$db)->tagSummarize("john.doe@example.com")->thenReturn(new Result($this->tags)); $this->assertXmlStringEqualsXmlString($this->serialization, (new OPML)->export("john.doe@example.com")); } public function testExportToFlatOpml(): void { - \Phake::when(Arsse::$db)->folderList("john.doe@example.com")->thenReturn(new Result($this->folders)); - \Phake::when(Arsse::$db)->subscriptionList("john.doe@example.com")->thenReturn(new Result($this->subscriptions)); - \Phake::when(Arsse::$db)->tagSummarize("john.doe@example.com")->thenReturn(new Result($this->tags)); $this->assertXmlStringEqualsXmlString($this->serializationFlat, (new OPML)->export("john.doe@example.com", true)); } public function testExportToOpmlAMissingUser(): void { - \Phake::when(Arsse::$db)->userExists->thenReturn(false); + $this->dbMock->userExists->returns(false); $this->assertException("doesNotExist", "User", "ExceptionConflict"); (new OPML)->export("john.doe@example.com"); } @@ -108,13 +108,15 @@ OPML_EXPORT_SERIALIZATION; /** @dataProvider provideParserData */ public function testParseOpmlForImport(string $file, bool $flat, $exp): void { $data = file_get_contents(\JKingWeb\Arsse\DOCROOT."Import/OPML/$file"); - // set up a partial mock to make the ImportExport::parse() method visible - $parser = \Phake::makeVisible(\Phake::partialMock(OPML::class)); - if ($exp instanceof \JKingWeb\Arsse\AbstractException) { + // make the ImportExport::parse() method visible + $parser = new OPML; + $parseFunc = new \ReflectionMethod($parser, "parse"); + $parseFunc->setAccessible(true); + if ($exp instanceof \Exception) { $this->assertException($exp); - $parser->parse($data, $flat); + $parseFunc->invoke($parser, $data, $flat); } else { - $this->assertSame($exp, $parser->parse($data, $flat)); + $this->assertSame($exp, $parseFunc->invoke($parser, $data, $flat)); } } diff --git a/tests/cases/Misc/TestDate.php b/tests/cases/Misc/TestDate.php index 5c16d352..e0cbbade 100644 --- a/tests/cases/Misc/TestDate.php +++ b/tests/cases/Misc/TestDate.php @@ -10,10 +10,6 @@ use JKingWeb\Arsse\Misc\Date; /** @covers \JKingWeb\Arsse\Misc\Date */ class TestDate extends \JKingWeb\Arsse\Test\AbstractTest { - public function setUp(): void { - self::clearData(); - } - public function testNormalizeADate(): void { $exp = new \DateTimeImmutable("2018-01-01T00:00:00Z"); $this->assertEquals($exp, Date::normalize(1514764800)); diff --git a/tests/cases/Misc/TestURL.php b/tests/cases/Misc/TestURL.php index 52bafa42..eddc67ed 100644 --- a/tests/cases/Misc/TestURL.php +++ b/tests/cases/Misc/TestURL.php @@ -10,9 +10,6 @@ use JKingWeb\Arsse\Misc\URL; /** @covers \JKingWeb\Arsse\Misc\URL */ class TestURL extends \JKingWeb\Arsse\Test\AbstractTest { - public function setUp(): void { - self::clearData(); - } /** @dataProvider provideNormalizations */ public function testNormalizeAUrl(string $url, string $exp, string $user = null, string $pass = null): void { diff --git a/tests/cases/Misc/TestValueInfo.php b/tests/cases/Misc/TestValueInfo.php index efa1becf..90b4be98 100644 --- a/tests/cases/Misc/TestValueInfo.php +++ b/tests/cases/Misc/TestValueInfo.php @@ -12,9 +12,6 @@ use JKingWeb\Arsse\Test\Result; /** @covers \JKingWeb\Arsse\Misc\ValueInfo */ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { - public function setUp(): void { - self::clearData(); - } public function testGetIntegerInfo(): void { $tests = [ diff --git a/tests/cases/REST/Fever/TestAPI.php b/tests/cases/REST/Fever/TestAPI.php index eb44d660..3128c446 100644 --- a/tests/cases/REST/Fever/TestAPI.php +++ b/tests/cases/REST/Fever/TestAPI.php @@ -24,7 +24,8 @@ use Laminas\Diactoros\Response\EmptyResponse; class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { /** @var \JKingWeb\Arsse\REST\Fever\API */ protected $h; - + protected $hMock; + protected $userId = "john.doe@example.com"; protected $articles = [ 'db' => [ [ @@ -141,35 +142,35 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { ], ], ]; + protected function v($value) { return $value; } - protected function req($dataGet, $dataPost = "", string $method = "POST", string $type = null, string $target = "", string $user = null): ServerRequest { + protected function req($dataGet, $dataPost = "", string $method = "POST", ?string $type = null, string $target = "", ?string $user = null): ResponseInterface { + Arsse::$db = $this->dbMock->get(); + $this->h = $this->hMock->get(); $prefix = "/fever/"; $url = $prefix.$target; $type = $type ?? "application/x-www-form-urlencoded"; - return $this->serverRequest($method, $url, $prefix, [], [], $dataPost, $type, $dataGet, $user); + return $this->h->dispatch($this->serverRequest($method, $url, $prefix, [], [], $dataPost, $type, $dataGet, $user)); } public function setUp(): void { self::clearData(); self::setConf(); // create a mock user manager - Arsse::$user = \Phake::mock(User::class); - \Phake::when(Arsse::$user)->auth->thenReturn(true); - Arsse::$user->id = "john.doe@example.com"; + $this->userMock = $this->mock(User::class); + $this->userMock->auth->returns(true); + Arsse::$user = $this->userMock->get(); + Arsse::$user->id = $this->userId; // create a mock database interface - Arsse::$db = \Phake::mock(Database::class); - \Phake::when(Arsse::$db)->begin->thenReturn(\Phake::mock(Transaction::class)); - \Phake::when(Arsse::$db)->tokenLookup->thenReturn(['user' => "john.doe@example.com"]); + $this->dbMock = $this->mock(Database::class); + $this->dbMock->begin->returns($this->mock(Transaction::class)); + $this->dbMock->tokenLookup->returns(['user' => "john.doe@example.com"]); // instantiate the handler as a partial mock to simplify testing - $this->h = \Phake::partialMock(API::class); - \Phake::when($this->h)->baseResponse->thenReturn([]); - } - - public function tearDown(): void { - self::clearData(); + $this->hMock = $this->partialMock(API::class); + $this->hMock->baseResponse->returns([]); } /** @dataProvider provideTokenAuthenticationRequests */ @@ -179,17 +180,16 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { 'userSessionEnforced' => $tokenEnforced, ], true); Arsse::$user->id = null; - \Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("subjectMissing")); - \Phake::when(Arsse::$db)->tokenLookup("fever.login", "validtoken")->thenReturn(['user' => "jane.doe@example.com"]); + $this->dbMock->tokenLookup->throws(new ExceptionInput("subjectMissing")); + $this->dbMock->tokenLookup->with("fever.login", "validtoken")->returns(['user' => "jane.doe@example.com"]); // test only the authentication process - \Phake::when($this->h)->baseResponse->thenReturnCallback(function(bool $authenticated) { + $this->hMock->baseResponse->does(function(bool $authenticated) { return ['auth' => (int) $authenticated]; }); - \Phake::when($this->h)->processRequest->thenReturnCallback(function($out, $G, $P) { + $this->hMock->processRequest->does(function($out, $G, $P) { return $out; }); - $act = $this->h->dispatch($this->req($dataGet, $dataPost, "POST", null, "", $httpUser)); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req($dataGet, $dataPost, "POST", null, "", $httpUser)); } public function provideTokenAuthenticationRequests(): iterable { @@ -245,12 +245,12 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { } public function testListGroups(): void { - \Phake::when(Arsse::$db)->tagList(Arsse::$user->id)->thenReturn(new Result([ + $this->dbMock->tagList->with($this->userId)->returns(new Result([ ['id' => 1, 'name' => "Fascinating", 'subscriptions' => 2], ['id' => 2, 'name' => "Interesting", 'subscriptions' => 2], ['id' => 3, 'name' => "Boring", 'subscriptions' => 0], ])); - \Phake::when(Arsse::$db)->tagSummarize(Arsse::$user->id)->thenReturn(new Result([ + $this->dbMock->tagSummarize->with($this->userId)->returns(new Result([ ['id' => 1, 'name' => "Fascinating", 'subscription' => 1], ['id' => 1, 'name' => "Fascinating", 'subscription' => 2], ['id' => 2, 'name' => "Interesting", 'subscription' => 1], @@ -267,17 +267,16 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { ['group_id' => 2, 'feed_ids' => "1,3"], ], ]); - $act = $this->h->dispatch($this->req("api&groups")); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api&groups")); } public function testListFeeds(): void { - \Phake::when(Arsse::$db)->subscriptionList(Arsse::$user->id)->thenReturn(new Result([ + $this->dbMock->subscriptionList->with($this->userId)->returns(new Result([ ['id' => 1, 'feed' => 5, 'title' => "Ankh-Morpork News", 'url' => "http://example.com/feed", 'source' => "http://example.com/", 'edited' => "2019-01-01 21:12:00", 'icon_url' => "http://example.com/favicon.ico", 'icon_id' => 42], ['id' => 2, 'feed' => 9, 'title' => "Ook, Ook Eek Ook!", 'url' => "http://example.net/feed", 'source' => "http://example.net/", 'edited' => "1988-06-24 12:21:00", 'icon_url' => "", 'icon_id' => null], ['id' => 3, 'feed' => 1, 'title' => "The Last Soul", 'url' => "http://example.org/feed", 'source' => "http://example.org/", 'edited' => "1991-08-12 03:22:00", 'icon_url' => "http://example.org/favicon.ico", 'icon_id' => 42], ])); - \Phake::when(Arsse::$db)->tagSummarize(Arsse::$user->id)->thenReturn(new Result([ + $this->dbMock->tagSummarize->with($this->userId)->returns(new Result([ ['id' => 1, 'name' => "Fascinating", 'subscription' => 1], ['id' => 1, 'name' => "Fascinating", 'subscription' => 2], ['id' => 2, 'name' => "Interesting", 'subscription' => 1], @@ -294,23 +293,21 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { ['group_id' => 2, 'feed_ids' => "1,3"], ], ]); - $act = $this->h->dispatch($this->req("api&feeds")); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api&feeds")); } /** @dataProvider provideItemListContexts */ public function testListItems(string $url, Context $c, bool $desc): void { $fields = ["id", "subscription", "title", "author", "content", "url", "starred", "unread", "published_date"]; $order = [$desc ? "id desc" : "id"]; - \Phake::when(Arsse::$db)->articleList->thenReturn(new Result($this->articles['db'])); - \Phake::when(Arsse::$db)->articleCount(Arsse::$user->id, (new Context)->hidden(false))->thenReturn(1024); + $this->dbMock->articleList->returns(new Result($this->articles['db'])); + $this->dbMock->articleCount->with($this->userId, (new Context)->hidden(false))->returns(1024); $exp = new JsonResponse([ 'items' => $this->articles['rest'], 'total_items' => 1024, ]); - $act = $this->h->dispatch($this->req("api&$url")); - $this->assertMessage($exp, $act); - \Phake::verify(Arsse::$db)->articleList(Arsse::$user->id, $c, $fields, $order); + $this->assertMessage($exp, $this->req("api&$url")); + $this->dbMock->articleList->calledWith($this->userId, $this->equalTo($c), $fields, $order); } public function provideItemListContexts(): iterable { @@ -332,35 +329,34 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { public function testListItemIds(): void { $saved = [['id' => 1],['id' => 2],['id' => 3]]; $unread = [['id' => 4],['id' => 5],['id' => 6]]; - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->starred(true)->hidden(false))->thenReturn(new Result($saved)); - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->unread(true)->hidden(false))->thenReturn(new Result($unread)); + $this->dbMock->articleList->with($this->userId, (new Context)->starred(true)->hidden(false))->returns(new Result($saved)); + $this->dbMock->articleList->with($this->userId, (new Context)->unread(true)->hidden(false))->returns(new Result($unread)); $exp = new JsonResponse(['saved_item_ids' => "1,2,3"]); - $this->assertMessage($exp, $this->h->dispatch($this->req("api&saved_item_ids"))); + $this->assertMessage($exp, $this->req("api&saved_item_ids")); $exp = new JsonResponse(['unread_item_ids' => "4,5,6"]); - $this->assertMessage($exp, $this->h->dispatch($this->req("api&unread_item_ids"))); + $this->assertMessage($exp, $this->req("api&unread_item_ids")); } public function testListHotLinks(): void { // hot links are not actually implemented, so an empty array should be all we get $exp = new JsonResponse(['links' => []]); - $this->assertMessage($exp, $this->h->dispatch($this->req("api&links"))); + $this->assertMessage($exp, $this->req("api&links")); } /** @dataProvider provideMarkingContexts */ public function testSetMarks(string $post, Context $c, array $data, array $out): void { $saved = [['id' => 1],['id' => 2],['id' => 3]]; $unread = [['id' => 4],['id' => 5],['id' => 6]]; - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->starred(true)->hidden(false))->thenReturn(new Result($saved)); - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->unread(true)->hidden(false))->thenReturn(new Result($unread)); - \Phake::when(Arsse::$db)->articleMark->thenReturn(0); - \Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), (new Context)->article(2112))->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing")); + $this->dbMock->articleList->with($this->userId, (new Context)->starred(true)->hidden(false))->returns(new Result($saved)); + $this->dbMock->articleList->with($this->userId, (new Context)->unread(true)->hidden(false))->returns(new Result($unread)); + $this->dbMock->articleMark->returns(0); + $this->dbMock->articleMark->with($this->userId, $this->anything(), (new Context)->article(2112))->throws(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing")); $exp = new JsonResponse($out); - $act = $this->h->dispatch($this->req("api", $post)); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api", $post)); if ($c && $data) { - \Phake::verify(Arsse::$db)->articleMark(Arsse::$user->id, $data, $c); + $this->dbMock->articleMark->calledWith($this->userId, $data, $this->equalTo($c)); } else { - \Phake::verify(Arsse::$db, \Phake::times(0))->articleMark; + $this->dbMock->articleMark->never()->called(); } } @@ -368,17 +364,16 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { public function testSetMarksWithQuery(string $get, Context $c, array $data, array $out): void { $saved = [['id' => 1],['id' => 2],['id' => 3]]; $unread = [['id' => 4],['id' => 5],['id' => 6]]; - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->starred(true)->hidden(false))->thenReturn(new Result($saved)); - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->unread(true)->hidden(false))->thenReturn(new Result($unread)); - \Phake::when(Arsse::$db)->articleMark->thenReturn(0); - \Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), (new Context)->article(2112))->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing")); + $this->dbMock->articleList->with($this->userId, (new Context)->starred(true)->hidden(false))->returns(new Result($saved)); + $this->dbMock->articleList->with($this->userId, (new Context)->unread(true)->hidden(false))->returns(new Result($unread)); + $this->dbMock->articleMark->returns(0); + $this->dbMock->articleMark->with($this->userId, $this->anything(), (new Context)->article(2112))->throws(new \JKingWeb\Arsse\Db\ExceptionInput("subjectMissing")); $exp = new JsonResponse($out); - $act = $this->h->dispatch($this->req("api&$get")); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api&$get")); if ($c && $data) { - \Phake::verify(Arsse::$db)->articleMark(Arsse::$user->id, $data, $c); + $this->dbMock->articleMark->calledWith($this->userId, $data, $this->equalTo($c)); } else { - \Phake::verify(Arsse::$db, \Phake::times(0))->articleMark; + $this->dbMock->articleMark->never()->called(); } } @@ -421,97 +416,89 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { } /** @dataProvider provideInvalidRequests */ - public function testSendInvalidRequests(ServerRequest $req, ResponseInterface $exp): void { - $this->assertMessage($exp, $this->h->dispatch($req)); + public function testSendInvalidRequests(string $get, string $post, string $method, ?string $type, ResponseInterface $exp): void { + $this->assertMessage($exp, $this->req($get, $post, $method, $type)); } public function provideInvalidRequests(): iterable { return [ - 'Not an API request' => [$this->req(""), new EmptyResponse(404)], - 'Wrong method' => [$this->req("api", "", "PUT"), new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])], - 'Non-standard method' => [$this->req("api", "", "GET"), new JsonResponse([])], - 'Wrong content type' => [$this->req("api", '{"api_key":"validToken"}', "POST", "application/json"), new EmptyResponse(415, ['Accept' => "application/x-www-form-urlencoded, multipart/form-data"])], - 'Non-standard content type' => [$this->req("api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1"), new JsonResponse([])], + 'Not an API request' => ["", "", "POST", null, new EmptyResponse(404)], + 'Wrong method' => ["api", "", "PUT", null, new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])], + 'Non-standard method' => ["api", "", "GET", null, new JsonResponse([])], + 'Wrong content type' => ["api", '{"api_key":"validToken"}', "POST", "application/json", new EmptyResponse(415, ['Accept' => "application/x-www-form-urlencoded, multipart/form-data"])], + 'Non-standard content type' => ["api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1", new JsonResponse([])], ]; } public function testMakeABaseQuery(): void { - $this->h = \Phake::partialMock(API::class); - \Phake::when($this->h)->logIn->thenReturn(true); - \Phake::when(Arsse::$db)->subscriptionRefreshed(Arsse::$user->id)->thenReturn(new \DateTimeImmutable("2000-01-01T00:00:00Z")); + $this->hMock->baseResponse->forwards(); + $this->hMock->logIn->returns(true); + $this->dbMock->subscriptionRefreshed->with($this->userId)->returns(new \DateTimeImmutable("2000-01-01T00:00:00Z")); $exp = new JsonResponse([ 'api_version' => API::LEVEL, 'auth' => 1, 'last_refreshed_on_time' => 946684800, ]); - $act = $this->h->dispatch($this->req("api")); - $this->assertMessage($exp, $act); - \Phake::when(Arsse::$db)->subscriptionRefreshed(Arsse::$user->id)->thenReturn(null); // no subscriptions + $this->assertMessage($exp, $this->req("api")); + $this->dbMock->subscriptionRefreshed->with($this->userId)->returns(null); // no subscriptions $exp = new JsonResponse([ 'api_version' => API::LEVEL, 'auth' => 1, 'last_refreshed_on_time' => null, ]); - $act = $this->h->dispatch($this->req("api")); - $this->assertMessage($exp, $act); - \Phake::when($this->h)->logIn->thenReturn(false); + $this->assertMessage($exp, $this->req("api")); + $this->hMock->logIn->returns(false); $exp = new JsonResponse([ 'api_version' => API::LEVEL, 'auth' => 0, ]); - $act = $this->h->dispatch($this->req("api")); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api")); } public function testUndoReadMarks(): void { $unread = [['id' => 4],['id' => 5],['id' => 6]]; $out = ['unread_item_ids' => "4,5,6"]; - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->limit(1)->hidden(false), ["marked_date"], ["marked_date desc"])->thenReturn(new Result([['marked_date' => "2000-01-01 00:00:00"]])); - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->unread(true)->hidden(false))->thenReturn(new Result($unread)); - \Phake::when(Arsse::$db)->articleMark->thenReturn(0); + $this->dbMock->articleList->with($this->userId, $this->equalTo((new Context)->limit(1)->hidden(false)), ["marked_date"], ["marked_date desc"])->returns(new Result([['marked_date' => "2000-01-01 00:00:00"]])); + $this->dbMock->articleList->with($this->userId, $this->equalTo((new Context)->unread(true)->hidden(false)))->returns(new Result($unread)); + $this->dbMock->articleMark->returns(0); $exp = new JsonResponse($out); - $act = $this->h->dispatch($this->req("api", ['unread_recently_read' => 1])); - $this->assertMessage($exp, $act); - \Phake::verify(Arsse::$db)->articleMark(Arsse::$user->id, ['read' => false], (new Context)->unread(false)->markedSince("1999-12-31T23:59:45Z")->hidden(false)); - \Phake::when(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->limit(1)->hidden(false), ["marked_date"], ["marked_date desc"])->thenReturn(new Result([])); - $act = $this->h->dispatch($this->req("api", ['unread_recently_read' => 1])); - $this->assertMessage($exp, $act); - \Phake::verify(Arsse::$db)->articleMark; // only called one time, above + $this->assertMessage($exp, $this->req("api", ['unread_recently_read' => 1])); + $this->dbMock->articleMark->calledWith($this->userId, ['read' => false], $this->equalTo((new Context)->unread(false)->markedSince("1999-12-31T23:59:45Z")->hidden(false))); + $this->dbMock->articleList->with($this->userId, (new Context)->limit(1)->hidden(false), ["marked_date"], ["marked_date desc"])->returns(new Result([])); + $this->assertMessage($exp, $this->req("api", ['unread_recently_read' => 1])); + $this->dbMock->articleMark->once()->called(); // only called one time, above } public function testOutputToXml(): void { - \Phake::when($this->h)->processRequest->thenReturn([ + $this->hMock->processRequest->returns([ 'items' => $this->articles['rest'], 'total_items' => 1024, ]); $exp = new XmlResponse("1018Article title 1<p>Article content 1</p>http://example.com/1009466848001028Article title 2<p>Article content 2</p>http://example.com/2019467712001039Article title 3<p>Article content 3</p>http://example.com/3109468576001049Article title 4<p>Article content 4</p>http://example.com/41194694400010510Article title 5<p>Article content 5</p>http://example.com/5009470304001024"); - $act = $this->h->dispatch($this->req("api=xml")); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api=xml")); } public function testListFeedIcons(): void { $iconType = (new \ReflectionClassConstant(API::class, "GENERIC_ICON_TYPE"))->getValue(); $iconData = (new \ReflectionClassConstant(API::class, "GENERIC_ICON_DATA"))->getValue(); - \Phake::when(Arsse::$db)->iconList->thenReturn(new Result($this->v([ + $this->dbMock->iconList->returns(new Result($this->v([ ['id' => 42, 'type' => "image/svg+xml", 'data' => ""], ['id' => 44, 'type' => null, 'data' => "IMAGE DATA"], ['id' => 47, 'type' => null, 'data' => null], ]))); - $act = $this->h->dispatch($this->req("api&favicons")); $exp = new JsonResponse(['favicons' => [ ['id' => 0, 'data' => $iconType.",".$iconData], ['id' => 42, 'data' => "image/svg+xml;base64,PHN2Zy8+"], ['id' => 44, 'data' => "application/octet-stream;base64,SU1BR0UgREFUQQ=="], ]]); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api&favicons")); } public function testAnswerOptionsRequest(): void { - $act = $this->h->dispatch($this->req("api", "", "OPTIONS")); $exp = new EmptyResponse(204, [ 'Allow' => "POST", 'Accept' => "application/x-www-form-urlencoded, multipart/form-data", ]); - $this->assertMessage($exp, $act); + $this->assertMessage($exp, $this->req("api", "", "OPTIONS")); } } diff --git a/tests/cases/REST/Fever/TestUser.php b/tests/cases/REST/Fever/TestUser.php index 2764c420..dae49939 100644 --- a/tests/cases/REST/Fever/TestUser.php +++ b/tests/cases/REST/Fever/TestUser.php @@ -19,7 +19,7 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { protected $u; public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); // create a mock user manager Arsse::$user = \Phake::mock(User::class); @@ -31,10 +31,6 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { $this->u = new FeverUser(); } - public function tearDown(): void { - self::clearData(); - } - /** @dataProvider providePasswordCreations */ public function testRegisterAUserPassword(string $user, string $password = null, $exp): void { \Phake::when(Arsse::$user)->generatePassword->thenReturn("RANDOM_PASSWORD"); diff --git a/tests/cases/REST/Miniflux/TestToken.php b/tests/cases/REST/Miniflux/TestToken.php index e37af1b9..4857d028 100644 --- a/tests/cases/REST/Miniflux/TestToken.php +++ b/tests/cases/REST/Miniflux/TestToken.php @@ -21,7 +21,7 @@ class TestToken extends \JKingWeb\Arsse\Test\AbstractTest { protected $transaction; public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); // create a mock database interface Arsse::$db = \Phake::mock(Database::class); @@ -30,10 +30,6 @@ class TestToken extends \JKingWeb\Arsse\Test\AbstractTest { $this->h = new Token(); } - public function tearDown(): void { - self::clearData(); - } - protected function v($value) { return $value; } diff --git a/tests/cases/REST/Miniflux/TestV1.php b/tests/cases/REST/Miniflux/TestV1.php index ac50fda5..1450981a 100644 --- a/tests/cases/REST/Miniflux/TestV1.php +++ b/tests/cases/REST/Miniflux/TestV1.php @@ -71,7 +71,7 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest { } public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); // create a mock database interface Arsse::$db = \Phake::mock(Database::class); @@ -85,10 +85,6 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest { $this->h = new V1(); } - public function tearDown(): void { - self::clearData(); - } - protected function v($value) { return $value; } diff --git a/tests/cases/REST/NextcloudNews/TestV1_2.php b/tests/cases/REST/NextcloudNews/TestV1_2.php index 3d5a342a..016cc0c3 100644 --- a/tests/cases/REST/NextcloudNews/TestV1_2.php +++ b/tests/cases/REST/NextcloudNews/TestV1_2.php @@ -312,7 +312,7 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { } public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); // create a mock user manager Arsse::$user = \Phake::mock(User::class); @@ -326,10 +326,6 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest { $this->h = new V1_2(); } - public function tearDown(): void { - self::clearData(); - } - protected function v($value) { return $value; } diff --git a/tests/cases/REST/NextcloudNews/TestVersions.php b/tests/cases/REST/NextcloudNews/TestVersions.php index aadb88d5..b5d5679d 100644 --- a/tests/cases/REST/NextcloudNews/TestVersions.php +++ b/tests/cases/REST/NextcloudNews/TestVersions.php @@ -14,7 +14,7 @@ use Laminas\Diactoros\Response\EmptyResponse; /** @covers \JKingWeb\Arsse\REST\NextcloudNews\Versions */ class TestVersions extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { - self::clearData(); + parent::setUp(); } protected function req(string $method, string $target): ResponseInterface { diff --git a/tests/cases/REST/TestREST.php b/tests/cases/REST/TestREST.php index a7eb83e9..55da259c 100644 --- a/tests/cases/REST/TestREST.php +++ b/tests/cases/REST/TestREST.php @@ -63,11 +63,12 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { public function testAuthenticateRequests(array $serverParams, array $expAttr): void { $r = new REST(); // create a mock user manager - Arsse::$user = \Phake::mock(User::class); - \Phake::when(Arsse::$user)->auth->thenReturn(false); - \Phake::when(Arsse::$user)->auth("john.doe@example.com", "secret")->thenReturn(true); - \Phake::when(Arsse::$user)->auth("john.doe@example.com", "")->thenReturn(true); - \Phake::when(Arsse::$user)->auth("someone.else@example.com", "")->thenReturn(true); + $this->userMock = $this->mock(User::class); + $this->userMock->auth->returns(false); + $this->userMock->auth->with("john.doe@example.com", "secret")->returns(true); + $this->userMock->auth->with("john.doe@example.com", "")->returns(true); + $this->userMock->auth->with("someone.else@example.com", "")->returns(true); + Arsse::$user = $this->userMock->get(); // create an input server request $req = new ServerRequest($serverParams); // create the expected output @@ -150,13 +151,13 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideCorsNegotiations */ public function testNegotiateCors($origin, bool $exp, string $allowed = null, string $denied = null): void { self::setConf(); - $r = \Phake::partialMock(REST::class); - \Phake::when($r)->corsNormalizeOrigin->thenReturnCallback(function($origin) { + $rMock = $this->partialMock(REST::class); + $rMock->corsNormalizeOrigin->does(function($origin) { return $origin; }); $headers = isset($origin) ? ['Origin' => $origin] : []; $req = new Request("", "GET", "php://memory", $headers); - $act = $r->corsNegotiate($req, $allowed, $denied); + $act = $rMock->get()->corsNegotiate($req, $allowed, $denied); $this->assertSame($exp, $act); } @@ -251,15 +252,15 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideUnnormalizedResponses */ public function testNormalizeHttpResponses(ResponseInterface $res, ResponseInterface $exp, RequestInterface $req = null): void { - $r = \Phake::partialMock(REST::class); - \Phake::when($r)->corsNegotiate->thenReturn(true); - \Phake::when($r)->challenge->thenReturnCallback(function($res) { + $rMock = $this->partialMock(REST::class); + $rMock->corsNegotiate->returns(true); + $rMock->challenge->does(function($res) { return $res->withHeader("WWW-Authenticate", "Fake Value"); }); - \Phake::when($r)->corsApply->thenReturnCallback(function($res) { + $rMock->corsApply->does(function($res) { return $res; }); - $act = $r->normalizeResponse($res, $req); + $act = $rMock->get()->normalizeResponse($res, $req); $this->assertMessage($exp, $act); } @@ -287,30 +288,32 @@ class TestREST extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideMockRequests */ public function testDispatchRequests(ServerRequest $req, string $method, bool $called, string $class = "", string $target = ""): void { - $r = \Phake::partialMock(REST::class); - \Phake::when($r)->normalizeResponse->thenReturnCallback(function($res) { + $rMock = $this->partialMock(REST::class); + $rMock->normalizeResponse->does(function($res) { return $res; }); - \Phake::when($r)->authenticateRequest->thenReturnCallback(function($req) { + $rMock->authenticateRequest->does(function($req) { return $req; }); if ($called) { - $h = \Phake::mock($class); - \Phake::when(Arsse::$obj)->get($class)->thenReturn($h); - \Phake::when($h)->dispatch->thenReturn(new EmptyResponse(204)); + $hMock = $this->mock($class); + $hMock->dispatch->returns(new EmptyResponse(204)); + $this->objMock->get->with($class)->returns($hMock); + Arsse::$obj = $this->objMock->get(); } - $out = $r->dispatch($req); + $out = $rMock->get()->dispatch($req); $this->assertInstanceOf(ResponseInterface::class, $out); if ($called) { - \Phake::verify($r)->authenticateRequest; - \Phake::verify($h)->dispatch(\Phake::capture($in)); + $rMock->authenticateRequest->called(); + $hMock->dispatch->once()->called(); + $in = $hMock->dispatch->firstCall()->argument();; $this->assertSame($method, $in->getMethod()); $this->assertSame($target, $in->getRequestTarget()); } else { $this->assertSame(501, $out->getStatusCode()); } - \Phake::verify($r)->apiMatch; - \Phake::verify($r)->normalizeResponse; + $rMock->apiMatch->called(); + $rMock->normalizeResponse->called(); } public function provideMockRequests(): iterable { diff --git a/tests/cases/REST/TinyTinyRSS/TestIcon.php b/tests/cases/REST/TinyTinyRSS/TestIcon.php index 18735af7..842de996 100644 --- a/tests/cases/REST/TinyTinyRSS/TestIcon.php +++ b/tests/cases/REST/TinyTinyRSS/TestIcon.php @@ -20,7 +20,7 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest { protected $user = "john.doe@example.com"; public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); // create a mock user manager Arsse::$user = \Phake::mock(User::class); @@ -29,10 +29,6 @@ class TestIcon extends \JKingWeb\Arsse\Test\AbstractTest { $this->h = new Icon(); } - public function tearDown(): void { - self::clearData(); - } - protected function req(string $target, string $method = "GET", string $user = null): ResponseInterface { $prefix = "/tt-rss/feed-icons/"; $url = $prefix.$target; diff --git a/tests/cases/Service/TestSerial.php b/tests/cases/Service/TestSerial.php index 93209798..2749f95f 100644 --- a/tests/cases/Service/TestSerial.php +++ b/tests/cases/Service/TestSerial.php @@ -14,7 +14,7 @@ use JKingWeb\Arsse\Service\Serial\Driver; /** @covers \JKingWeb\Arsse\Service\Serial\Driver */ class TestSerial extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); Arsse::$db = \Phake::mock(Database::class); } diff --git a/tests/cases/Service/TestService.php b/tests/cases/Service/TestService.php index 9aef50cb..31323021 100644 --- a/tests/cases/Service/TestService.php +++ b/tests/cases/Service/TestService.php @@ -16,7 +16,7 @@ class TestService extends \JKingWeb\Arsse\Test\AbstractTest { protected $srv; public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); Arsse::$db = \Phake::mock(Database::class); $this->srv = new Service(); diff --git a/tests/cases/Service/TestSubprocess.php b/tests/cases/Service/TestSubprocess.php index b6ca047d..763102b0 100644 --- a/tests/cases/Service/TestSubprocess.php +++ b/tests/cases/Service/TestSubprocess.php @@ -13,7 +13,7 @@ use JKingWeb\Arsse\Service\Subprocess\Driver; /** @covers \JKingWeb\Arsse\Service\Subprocess\Driver */ class TestSubprocess extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); } diff --git a/tests/cases/TestArsse.php b/tests/cases/TestArsse.php index a15a8009..2173db83 100644 --- a/tests/cases/TestArsse.php +++ b/tests/cases/TestArsse.php @@ -17,22 +17,23 @@ class TestArsse extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { self::clearData(false); } - public function tearDown(): void { - self::clearData(); - } public function testLoadExistingData(): void { - $lang = Arsse::$lang = \Phake::mock(Lang::class); - $db = Arsse::$db = \Phake::mock(Database::class); - $user = Arsse::$user = \Phake::mock(User::class); - $conf1 = Arsse::$conf = \Phake::mock(Conf::class); + $lang = $this->mock(Lang::class); + $db = $this->mock(Database::class); + $user = $this->mock(User::class); + $conf1 = $this->mock(Conf::class); + Arsse::$lang = $lang->get(); + Arsse::$db = $db->get(); + Arsse::$user = $user->get(); + Arsse::$conf = $conf1->get(); $conf2 = (new Conf)->import(['lang' => "test"]); Arsse::load($conf2); $this->assertSame($conf2, Arsse::$conf); - $this->assertSame($lang, Arsse::$lang); - $this->assertSame($db, Arsse::$db); - $this->assertSame($user, Arsse::$user); - \Phake::verify($lang)->set("test"); + $this->assertSame($lang->get(), Arsse::$lang); + $this->assertSame($db->get(), Arsse::$db); + $this->assertSame($user->get(), Arsse::$user); + $lang->set->calledWith("test"); } public function testLoadNewData(): void { diff --git a/tests/cases/User/TestInternal.php b/tests/cases/User/TestInternal.php index fa42de17..ce820444 100644 --- a/tests/cases/User/TestInternal.php +++ b/tests/cases/User/TestInternal.php @@ -14,7 +14,7 @@ use JKingWeb\Arsse\User\Internal\Driver; /** @covers \JKingWeb\Arsse\User\Internal\Driver */ class TestInternal extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); // create a mock database interface Arsse::$db = \Phake::mock(Database::class); diff --git a/tests/cases/User/TestUser.php b/tests/cases/User/TestUser.php index e9a45c9f..6400555e 100644 --- a/tests/cases/User/TestUser.php +++ b/tests/cases/User/TestUser.php @@ -17,7 +17,7 @@ use JKingWeb\Arsse\User\Driver; /** @covers \JKingWeb\Arsse\User */ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { public function setUp(): void { - self::clearData(); + parent::setUp(); self::setConf(); // create a mock database interface Arsse::$db = \Phake::mock(Database::class); diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index f807e6bb..1eb1b2e3 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -6,6 +6,8 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Test; +use Eloquent\Phony\Mock\Handle\InstanceHandle; +use Eloquent\Phony\Phpunit\Phony; use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\RequestException; use JKingWeb\Arsse\Exception; @@ -29,12 +31,20 @@ use Laminas\Diactoros\Response\XmlResponse; abstract class AbstractTest extends \PHPUnit\Framework\TestCase { use \DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; + protected $objMock; + protected $confMock; + protected $langMock; + protected $dbMock; + protected $userMock; + + public function setUp(): void { self::clearData(); - } - - public function tearDown(): void { - self::clearData(); + // create the object factory as a mock + $this->objMock = Arsse::$obj = $this->mock(Factory::class); + $this->objMock->get->does(function(string $class) { + return new $class; + }); } public static function clearData(bool $loadLang = true): void { @@ -46,11 +56,6 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { } if ($loadLang) { Arsse::$lang = new \JKingWeb\Arsse\Lang(); - // also create the object factory as a mock - Arsse::$obj = \Phake::mock(Factory::class); - \Phake::when(Arsse::$obj)->get->thenReturnCallback(function(string $class) { - return new $class; - }); } } @@ -340,12 +345,20 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { /** Guzzle's exception classes require some fairly complicated construction; this abstracts it all away so that only message and code need be supplied */ protected function mockGuzzleException(string $class, ?string $message = null, ?int $code = null, ?\Throwable $e = null): GuzzleException { if (is_a($class, RequestException::class, true)) { - $req = \Phake::mock(RequestInterface::class); - $res = \Phake::mock(ResponseInterface::class); - \Phake::when($res)->getStatusCode->thenReturn($code ?? 0); - return new $class($message ?? "", $req, $res, $e); + $req = $this->mock(RequestInterface::class); + $res = $this->mock(ResponseInterface::class); + $res->getStatusCode->returns($code ?? 0); + return new $class($message ?? "", $req->get(), $res->get(), $e); } else { return new $class($message ?? "", $code ?? 0, $e); } } + + protected function mock(string $class): InstanceHandle { + return Phony::mock($class); + } + + protected function partialMock(string $class, ...$argument): InstanceHandle { + return Phony::partialMock($class, $argument); + } } diff --git a/vendor-bin/phpunit/composer.json b/vendor-bin/phpunit/composer.json index 44e3a6e5..48bcb5cd 100644 --- a/vendor-bin/phpunit/composer.json +++ b/vendor-bin/phpunit/composer.json @@ -5,6 +5,7 @@ "phake/phake": "^3.0", "clue/arguments": "^2.0", "mikey179/vfsstream": "^1.6", - "webmozart/glob": "^4.1" + "webmozart/glob": "^4.1", + "eloquent/phony-phpunit": "^6.0 || ^7.0" } } diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index fb1ecc23..a7250dfc 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9c0d657e9fcab3d3be0467bbdc300a0a", + "content-hash": "fda9bd2446005dfe56a223890cad0849", "packages": [], "packages-dev": [ { @@ -188,6 +188,153 @@ ], "time": "2020-11-10T18:47:58+00:00" }, + { + "name": "eloquent/phony", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/eloquent/phony.git", + "reference": "f34d67d6db6b6f351ea7e8aa8066107e756ec26b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/eloquent/phony/zipball/f34d67d6db6b6f351ea7e8aa8066107e756ec26b", + "reference": "f34d67d6db6b6f351ea7e8aa8066107e756ec26b", + "shasum": "" + }, + "require": { + "php": "^7.3 || ^8" + }, + "require-dev": { + "eloquent/code-style": "^1.0", + "eloquent/phpstan-phony": "^0.7", + "errors/exceptions": "^0.2", + "ext-pdo": "*", + "friendsofphp/php-cs-fixer": "^2", + "hamcrest/hamcrest-php": "^2", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Eloquent\\Phony\\": "src" + }, + "files": [ + "src/initialize.php", + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Erin Millard", + "email": "ezzatron@gmail.com", + "homepage": "http://ezzatron.com/" + } + ], + "description": "Mocks, stubs, and spies for PHP.", + "homepage": "http://eloquent-software.com/phony/", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "mocking", + "spy", + "stub", + "stubbing", + "test" + ], + "support": { + "issues": "https://github.com/eloquent/phony/issues", + "source": "https://github.com/eloquent/phony/tree/5.0.2" + }, + "time": "2021-02-17T01:45:10+00:00" + }, + { + "name": "eloquent/phony-phpunit", + "version": "7.1.0", + "source": { + "type": "git", + "url": "https://github.com/eloquent/phony-phpunit.git", + "reference": "e77ff95ea6235211d4aae7e5f53488a5faebc2e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/eloquent/phony-phpunit/zipball/e77ff95ea6235211d4aae7e5f53488a5faebc2e0", + "reference": "e77ff95ea6235211d4aae7e5f53488a5faebc2e0", + "shasum": "" + }, + "require": { + "eloquent/phony": "^5", + "php": "^7.3 || ^8", + "phpunit/phpunit": "^9" + }, + "require-dev": { + "eloquent/code-style": "^1", + "eloquent/phpstan-phony": "^0.7", + "errors/exceptions": "^0.2", + "friendsofphp/php-cs-fixer": "^2", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Eloquent\\Phony\\Phpunit\\": "src" + }, + "files": [ + "src/initialize.php", + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Erin Millard", + "email": "ezzatron@gmail.com", + "homepage": "http://ezzatron.com/" + } + ], + "description": "Phony for PHPUnit.", + "homepage": "http://eloquent-software.com/phony/", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "mocking", + "spy", + "stub", + "stubbing", + "test" + ], + "support": { + "issues": "https://github.com/eloquent/phony-phpunit/issues", + "source": "https://github.com/eloquent/phony-phpunit/tree/7.1.0" + }, + "time": "2020-12-21T09:36:47+00:00" + }, { "name": "mikey179/vfsstream", "version": "v1.6.8", diff --git a/vendor-bin/robo/composer.json b/vendor-bin/robo/composer.json index 681352c4..b3180b72 100644 --- a/vendor-bin/robo/composer.json +++ b/vendor-bin/robo/composer.json @@ -1,6 +1,6 @@ { "require-dev": { - "consolidation/robo": "^2.2", + "consolidation/robo": "^3.0", "pear/archive_tar": "^1.4" } } diff --git a/vendor-bin/robo/composer.lock b/vendor-bin/robo/composer.lock index 8f50fb6d..2fc89c6d 100644 --- a/vendor-bin/robo/composer.lock +++ b/vendor-bin/robo/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1bd6e46df17a215ef177f27dadac115f", + "content-hash": "ee0b828426eaa5ff905ef60d9a4b9aca", "packages": [], "packages-dev": [ { @@ -235,51 +235,49 @@ }, { "name": "consolidation/robo", - "version": "2.2.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/consolidation/Robo.git", - "reference": "b365df174d9cfb0f5814e4f3275a1c558b17bc4c" + "reference": "734620ad3f9bb457fda1a52338b42439115cf941" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/Robo/zipball/b365df174d9cfb0f5814e4f3275a1c558b17bc4c", - "reference": "b365df174d9cfb0f5814e4f3275a1c558b17bc4c", + "url": "https://api.github.com/repos/consolidation/Robo/zipball/734620ad3f9bb457fda1a52338b42439115cf941", + "reference": "734620ad3f9bb457fda1a52338b42439115cf941", "shasum": "" }, "require": { - "consolidation/annotated-command": "^4.2.1", - "consolidation/config": "^1.2.1|^2", - "consolidation/log": "^1.1.1|^2.0.1", - "consolidation/output-formatters": "^4.1.1", + "consolidation/annotated-command": "^4.2.4", + "consolidation/config": "^1.2.1|^2.0.1", + "consolidation/log": "^1.1.1|^2.0.2", + "consolidation/output-formatters": "^4.1.2", "consolidation/self-update": "^1.2", - "league/container": "^2.4.1", + "league/container": "^3.3.1", "php": ">=7.1.3", - "symfony/console": "^4.4.11|^5", - "symfony/event-dispatcher": "^4.4.11|^5", - "symfony/filesystem": "^4.4.11|^5", - "symfony/finder": "^4.4.11|^5", - "symfony/process": "^4.4.11|^5", - "symfony/yaml": "^4.0 || ^5.0" + "symfony/console": "^4.4.19 || ^5", + "symfony/event-dispatcher": "^4.4.19 || ^5", + "symfony/filesystem": "^4.4.9 || ^5", + "symfony/finder": "^4.4.9 || ^5", + "symfony/process": "^4.4.9 || ^5", + "symfony/yaml": "^4.4 || ^5" }, "conflict": { "codegyre/robo": "*" }, "require-dev": { - "g1a/composer-test-scenarios": "^3", "natxet/cssmin": "3.0.4", "patchwork/jsqueeze": "^2", "pear/archive_tar": "^1.4.4", - "php-coveralls/php-coveralls": "^2.2", - "phpdocumentor/reflection-docblock": "^4.3.2", - "phpunit/phpunit": "^6.5.14", - "squizlabs/php_codesniffer": "^3" + "phpunit/phpunit": "^7.5.20 | ^8", + "squizlabs/php_codesniffer": "^3", + "yoast/phpunit-polyfills": "^0.2.0" }, "suggest": { - "henrikbjorn/lurker": "For monitoring filesystem changes in taskWatch", "natxet/cssmin": "For minifying CSS files in taskMinify", "patchwork/jsqueeze": "For minifying JS files in taskMinify", - "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively." + "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively.", + "totten/lurkerlite": "For monitoring filesystem changes in taskWatch" }, "bin": [ "robo" @@ -330,9 +328,9 @@ "description": "Modern task runner", "support": { "issues": "https://github.com/consolidation/Robo/issues", - "source": "https://github.com/consolidation/Robo/tree/2.2.2" + "source": "https://github.com/consolidation/Robo/tree/3.0.3" }, - "time": "2020-12-18T22:09:18+00:00" + "time": "2021-02-21T19:19:43+00:00" }, { "name": "consolidation/self-update", @@ -388,42 +386,6 @@ }, "time": "2020-04-13T02:49:20+00:00" }, - { - "name": "container-interop/container-interop", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/container-interop/container-interop.git", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "shasum": "" - }, - "require": { - "psr/container": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop", - "support": { - "issues": "https://github.com/container-interop/container-interop/issues", - "source": "https://github.com/container-interop/container-interop/tree/master" - }, - "abandoned": "psr/container", - "time": "2017-02-14T19:40:03+00:00" - }, { "name": "dflydev/dot-access-data", "version": "v1.1.0", @@ -540,37 +502,39 @@ }, { "name": "league/container", - "version": "2.5.0", + "version": "3.3.4", "source": { "type": "git", "url": "https://github.com/thephpleague/container.git", - "reference": "8438dc47a0674e3378bcce893a0a04d79a2c22b3" + "reference": "40aed0f11d16bc23f9d04a27acc3549cd1bb42ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/container/zipball/8438dc47a0674e3378bcce893a0a04d79a2c22b3", - "reference": "8438dc47a0674e3378bcce893a0a04d79a2c22b3", + "url": "https://api.github.com/repos/thephpleague/container/zipball/40aed0f11d16bc23f9d04a27acc3549cd1bb42ab", + "reference": "40aed0f11d16bc23f9d04a27acc3549cd1bb42ab", "shasum": "" }, "require": { - "container-interop/container-interop": "^1.2", - "php": "^5.4 || ^7.0 || ^8.0" + "php": "^7.0 || ^8.0", + "psr/container": "^1.0" }, "provide": { - "container-interop/container-interop-implementation": "^1.2", "psr/container-implementation": "^1.0" }, "replace": { "orno/di": "~2.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.36", - "scrutinizer/ocular": "^1.3", + "phpunit/phpunit": "^6.0", + "roave/security-advisories": "dev-master", + "scrutinizer/ocular": "^1.8", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "branch-alias": { + "dev-master": "3.x-dev", + "dev-3.x": "3.x-dev", "dev-2.x": "2.x-dev", "dev-1.x": "1.x-dev" } @@ -605,7 +569,7 @@ ], "support": { "issues": "https://github.com/thephpleague/container/issues", - "source": "https://github.com/thephpleague/container/tree/2.5.0" + "source": "https://github.com/thephpleague/container/tree/3.3.4" }, "funding": [ { @@ -613,7 +577,7 @@ "type": "github" } ], - "time": "2021-02-22T09:20:06+00:00" + "time": "2021-02-22T10:35:05+00:00" }, { "name": "pear/archive_tar",