diff --git a/src/PHPUnit/HasAction.php b/src/PHPUnit/HasAction.php new file mode 100644 index 0000000..d359620 --- /dev/null +++ b/src/PHPUnit/HasAction.php @@ -0,0 +1,85 @@ +groupTitle) { + return "contains action {$this->actionParams[0]}: {$this->actionParams[1]} under the groupTitle {$this->groupTitle}"; + } + + return "contains action {$this->actionParams[0]}: {$this->actionParams[1]}"; + } + + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + $action = $this->searchAction( + viewpoint: $other, + actionParams: $this->actionParams, + groupTitle: $this->groupTitle + ); + + if (is_null($action)) { + if ($returnResult) { + return false; + } else { + throw new ExpectationFailedException(trim($description)); + } + } else { + return true; + } + } + + protected function searchAction(Viewpoint $viewpoint, array $actionParams, ?string $groupTitle = null): ?Action + { + if (count($actionParams) != 2) { + throw InvalidArgumentException::create(2, "$actionParams is expected to be an array of exactly 2 items."); + } + + if (is_string($actionParams[0]) === false) { + throw InvalidArgumentException::create(2, "$actionParams[0] is expected to be a method."); + } + + $methodToCheck = $actionParams[0]; + $valueToHave = $actionParams[1]; + $checkedOnce = false; + + + $groups = $viewpoint->getActionGroups(); + $found = null; + + foreach ($groups as $group) { + $actions = $group->getActions(); + foreach ($actions as $action) { + if ($checkedOnce === false and method_exists($action, $methodToCheck) === false) { + throw InvalidArgumentException::create(2, "$actionParams[0] must be a valid method of " . Action::class . "."); + } else { + $checkedOnce = True; + } + + # Using KNF, !A or B is only false if A is true and B is not. + if ($action->$methodToCheck() == $valueToHave and (!is_null($groupTitle) or $group->getTitle() === $groupTitle)) { + $found = $action; + } + } + } + + return $found; + } +} \ No newline at end of file diff --git a/src/PHPUnit/LotGDTestCase.php b/src/PHPUnit/LotGDTestCase.php new file mode 100644 index 0000000..d40c91e --- /dev/null +++ b/src/PHPUnit/LotGDTestCase.php @@ -0,0 +1,204 @@ + [row1, row2], where each row is an associative array with each column name. + * @param PDO $pdo + * @param array|null $restrictToTables + */ + public function assertDataWasKeptIntact(array $before, PDO $pdo, ?array $restrictToTables = null): void + { + foreach ($before as $table => $rowsBefore) { + // Ignore table if $restrictToTables is an array and the table is not on the list. + if (is_array($restrictToTables) and empty($restrictToTables[$table])) { + continue; + } + + // Get all rows from table + $query = $pdo->query("SELECT * FROM `$table`"); + $rowsAfter = $query->fetchAll(PDO::FETCH_ASSOC); + + // Assert equal row counts + static::assertThat( + value: $rowsAfter, + constraint: new Count(count($rowsBefore)), + message: "Database assertion: Table <$table> does not match the expected number of rows. + Expected was <".count($rowsBefore).">, but found was <".count($rowsAfter).">" + ); + + // Assert equal contents + foreach ($rowsBefore as $key => $rowBefore) { + foreach ($rowBefore as $field => $value) { + static::assertThat( + value: $rowsAfter[$key][$field], + constraint: new IsEqual($value), + message: "Database assertion: In table <$table>, field <$field> does not match expected value <$value>, + is <{$rowsAfter[$key][$field]}> instead." + ); + } + } + } + } + + /** + * Asserts that a certain BuffMessageEvent with a specific text is contained in the lst of events + * @param Collection $events The list of events + * @param string $battleEventText The text to test for + * @param int $timesAtLeast Mininum number of times the message is expected to be in the event list + * @param ?int $timesAtMax Maximum number of times the message is expected to be in the event list, or $timesAtLeast if null. + */ + public function assertBuffEventMessageExists( + Collection $events, + string $battleEventText, + int $timesAtLeast = 1, + int $timesAtMax = null + ) { + $eventCounter = 0; + foreach($events as $event) { + if ($event instanceof BuffMessageEvent) { + if ($battleEventText === $event->getMessage()) { + $eventCounter++; + } + } + } + + if ($timesAtMax === null) { + $timesAtMax = $timesAtLeast; + } + + static::assertThat( + value: $eventCounter, + constraint: static::greaterThanOrEqual($timesAtLeast), + message: "The desired message {$battleEventText} has been found to exist less than {$timesAtLeast} times", + ); + + static::assertThat( + value: $eventCounter, + constraint: static::lessThanOrEqual($timesAtMax), + message: "The desired message {$battleEventText} has been found to exist more than {$timesAtLeast} times", + ); + } + + /** + * Helper method to take an action, or a series of actions, on a given viewpoint. + * + * @param Game $game + * @param Viewpoint $viewpoint + * @param array $actions + * @throws ActionNotFoundException + * @throws SceneNotFoundException + */ + public function takeActions(Game $game, Viewpoint $viewpoint, array $actions) + { + foreach ($actions as $action) { + foreach ($viewpoint->getActionGroups() as $group) { + foreach ($group->getActions() as $a) { + if ($a->getDestinationSceneId() == $action or $a->getTitle() == $action) { + $game->takeAction($a->getId()); + break 2; + } + } + } + } + } + + public function getAction(Viewpoint $viewpoint, array $actionParams, ?string $groupTitle = null): ?Action + { + if (count($actionParams) != 2) { + throw InvalidArgumentException::create(2, "$actionParams is expected to be an array of exactly 2 items."); + } + + if (is_string($actionParams[0]) === false) { + throw InvalidArgumentException::create(2, "$actionParams[0] is expected to be a method."); + } + + $methodToCheck = $actionParams[0]; + $valueToHave = $actionParams[1]; + $checkedOnce = false; + + + $groups = $viewpoint->getActionGroups(); + $found = null; + + foreach ($groups as $group) { + $actions = $group->getActions(); + foreach ($actions as $action) { + if ($checkedOnce === false and method_exists($action, $methodToCheck) === false) { + throw InvalidArgumentException::create(2, "$actionParams[0] must be a valid method of " . Action::class . "."); + } else { + $checkedOnce = True; + } + + # Using KNF, !A or B is only false if A is true and B is not. + if ($action->$methodToCheck() == $valueToHave and (!is_null($groupTitle) or $group->getTitle() === $groupTitle)) { + $found = $action; + } + } + } + + return $found; + } + + /** + * Asserts that a Viewpoint does not contain a given action. + * + * @param Viewpoint $viewpoint + * @param array $actionParams + * @param string|null $groupTitle + * @param string $message + */ + public function assertNotHasAction( + Viewpoint $viewpoint, + array $actionParams, + ?string $groupTitle = null, + string $message = '', + ): void { + $constraint = new LogicalNot( + new HasAction($actionParams, $groupTitle) + ); + + static::assertThat($viewpoint, $constraint, $message); + } + + /** + * Asserts that a Viewpoint contains a given action. + * + * @param Viewpoint $viewpoint + * @param array $actionParams, [$method, $value], where $method is a method of LotGD\Core\Action. Eg, ["getTitle", "The Forest"] + * @param string|null $groupTitle + * @param string $message + */ + public function assertHasAction( + Viewpoint $viewpoint, + array $actionParams, + ?string $groupTitle = null, + string $message = '', + ): void { + $constraint = new HasAction($actionParams, $groupTitle); + + static::assertThat($viewpoint, $constraint, $message); + } +} + diff --git a/tests/BattleTest.php b/tests/BattleTest.php index 8291b93..d6c7822 100644 --- a/tests/BattleTest.php +++ b/tests/BattleTest.php @@ -285,36 +285,6 @@ class BattleTest extends CoreModelTestCase return new Battle($this->getMockGame($character), $character, $monster); } - /** - * Asserts that a certain BuffMessageEvent with a specific text is contained in the lst of events - * @param Collection $events The list of events - * @param string $battleEventText The text to test for - * @param int $timesAtLeast Mininum number of times the message is expected to be in the event list - * @param int? $timesAtMax Maximum number of times the message is expected to be in the event list, or $timesAtLeast if null. - */ - protected function assertBuffEventMessageExists( - Collection $events, - string $battleEventText, - int $timesAtLeast = 1, - int $timesAtMax = null - ) { - $eventCounter = 0; - foreach($events as $event) { - if ($event instanceof BuffMessageEvent) { - if ($battleEventText === $event->getMessage()) { - $eventCounter++; - } - } - } - - if ($timesAtMax === null) { - $timesAtMax = $timesAtLeast; - } - - $this->assertGreaterThanOrEqual($timesAtLeast, $eventCounter); - $this->assertLessThanOrEqual($timesAtMax, $eventCounter); - } - /** * Tests normal buff messages - message upon start of the buff, message every * round (except when it's started), and the message displayed if the buff expires. diff --git a/tests/ModelTestCase.php b/tests/ModelTestCase.php index f259320..ec4ba03 100644 --- a/tests/ModelTestCase.php +++ b/tests/ModelTestCase.php @@ -18,6 +18,7 @@ use LotGD\Core\GameBuilder; use LotGD\Core\LibraryConfigurationManager; use LotGD\Core\Exceptions\InvalidConfigurationException; use LotGD\Core\ModelExtender; +use LotGD\Core\PHPUnit\LotGDTestCase; use Monolog\Handler\NullHandler; use Monolog\Handler\StreamHandler; use Monolog\Logger; @@ -27,7 +28,7 @@ use PHPUnit\Framework\TestCase; /** * Description of ModelTestCase */ -abstract class ModelTestCase extends TestCase +abstract class ModelTestCase extends LotGDTestCase { /** @var PDO */ static private $pdo = null; @@ -189,41 +190,6 @@ abstract class ModelTestCase extends TestCase $this->getEntityManager()->clear(); } - public function assertDataWasKeptIntact(?array $restrictToTables = null): void - { - // Assert that databases are the same before and after. - // TODO for module author: update list of tables below to include the - // tables you modify during registration/unregistration. - $dataSetBefore = $this->getDataSet(); - /** @var PDO $pdo */ - $pdo = $this->getConnection()[0]; - - foreach ($dataSetBefore as $table => $rowsBefore) { - // Ignore table if $restrictToTables is an array and the table is not on the list. - if (is_array($restrictToTables) and empty($restrictToTables[$table])) { - continue; - } - - $query = $pdo->query("SELECT * FROM `$table`"); - $rowsAfter = $query->fetchAll(PDO::FETCH_ASSOC); - - // Assert equal row counts - $this->assertCount(count($rowsBefore), $rowsAfter, - "Database assertion: Table <$table> does not match the expected number of rows. - Expected was <".count($rowsBefore).">, but found was <".count($rowsAfter).">" - ); - - foreach ($rowsBefore as $key => $rowBefore) { - foreach ($rowBefore as $field => $value) { - $this->assertEquals($value, $rowsAfter[$key][$field], - "Database assertion: In table <$table>, field <$field> does not match expected value <$value>, - is <{$rowsAfter[$key][$field]}> instead.", - ); - } - } - } - } - protected function flushAndClear() { $this->getEntityManager()->flush();