From 3ec1a05d824ebf3dafe7f3395c775d67facb14b9 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Thu, 14 Nov 2024 23:38:47 -0500 Subject: [PATCH] WIP on migrating Postgres integration tests --- tests/Integration/PgIntegrationTest.php | 60 ++++++++ tests/Integration/PostgreSQL/CountTest.php | 45 ++++++ tests/Integration/PostgreSQL/CustomTest.php | 98 +++++++++++++ .../Integration/PostgreSQL/DefinitionTest.php | 47 ++++++ tests/Integration/PostgreSQL/DeleteTest.php | 64 ++++++++ .../PostgreSQL/DocumentListTest.php | 45 ++++++ tests/Pest.php | 1 + tests/integration/postgresql/CountTest.php | 84 ----------- tests/integration/postgresql/CustomTest.php | 138 ------------------ .../integration/postgresql/DefinitionTest.php | 88 ----------- tests/integration/postgresql/DeleteTest.php | 99 ------------- tests/integration/postgresql/ThrowawayDb.php | 23 ++- 12 files changed, 377 insertions(+), 415 deletions(-) create mode 100644 tests/Integration/PgIntegrationTest.php create mode 100644 tests/Integration/PostgreSQL/CountTest.php create mode 100644 tests/Integration/PostgreSQL/CustomTest.php create mode 100644 tests/Integration/PostgreSQL/DefinitionTest.php create mode 100644 tests/Integration/PostgreSQL/DeleteTest.php create mode 100644 tests/Integration/PostgreSQL/DocumentListTest.php delete mode 100644 tests/integration/postgresql/CountTest.php delete mode 100644 tests/integration/postgresql/CustomTest.php delete mode 100644 tests/integration/postgresql/DefinitionTest.php delete mode 100644 tests/integration/postgresql/DeleteTest.php diff --git a/tests/Integration/PgIntegrationTest.php b/tests/Integration/PgIntegrationTest.php new file mode 100644 index 0000000..5e53482 --- /dev/null +++ b/tests/Integration/PgIntegrationTest.php @@ -0,0 +1,60 @@ + + * @license MIT + * @see https://github.com/Zaid-Ajaj/ThrowawayDb The origin concept + */ + +declare(strict_types=1); + +namespace Test\Integration; + +use BitBadger\PDODocument\{Configuration, Custom, Delete, DocumentException, Field}; +use BitBadger\PDODocument\Mapper\ExistsMapper; +use PHPUnit\Framework\TestCase; +use Test\Integration\PostgreSQL\ThrowawayDb; + +/** + * Integration Test Class wrapper for PostgreSQL integration tests + */ +class PgIntegrationTest extends TestCase +{ + /** @var string Database name for throwaway database */ + static private string $dbName = ''; + + public static function setUpBeforeClass(): void + { + self::$dbName = ThrowawayDb::create(false); + } + + protected function setUp(): void + { + parent::setUp(); + ThrowawayDb::loadData(); + } + + protected function tearDown(): void + { + Delete::byFields(ThrowawayDb::TABLE, [ Field::exists(Configuration::$idField)]); + parent::tearDown(); + } + + public static function tearDownAfterClass(): void + { + ThrowawayDb::destroy(self::$dbName); + self::$dbName = ''; + } + + /** + * Does the given named object exist in the database? + * + * @param string $name The name of the object whose existence should be verified + * @return bool True if the object exists, false if not + * @throws DocumentException If any is encountered + */ + protected function dbObjectExists(string $name): bool + { + return Custom::scalar('SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = :name)', + [':name' => $name], new ExistsMapper()); + } +} diff --git a/tests/Integration/PostgreSQL/CountTest.php b/tests/Integration/PostgreSQL/CountTest.php new file mode 100644 index 0000000..56e4795 --- /dev/null +++ b/tests/Integration/PostgreSQL/CountTest.php @@ -0,0 +1,45 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Count, Field}; +use Test\Integration\PostgreSQL\ThrowawayDb; + +pest()->group('integration', 'postgresql'); + +describe('::all()', function () { + test('counts all documents', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + }); +}); + +describe('::byFields()', function () { + test('counts for numeric range correctly', function () { + expect(Count::byFields(ThrowawayDb::TABLE, [Field::between('num_value', 10, 20)]))->toBe(3); + }); + test('counts for non-numeric range correctly', function () { + expect(Count::byFields(ThrowawayDb::TABLE, [Field::between('value', 'aardvark', 'apple')]))->toBe(1); + }); +}); + +describe('::byContains()', function () { + test('counts matching documents', function () { + expect(Count::byContains(ThrowawayDb::TABLE, ['value' => 'purple']))->toBe(2); + }); + test('returns 0 for no matching documents', function () { + expect(Count::byContains(ThrowawayDb::TABLE, ['value' => 'magenta']))->toBe(0); + }); +}); + +describe('::byJsonPath()', function () { + test('counts matching documents', function () { + expect(Count::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ < 5)'))->toBe(2); + }); + test('returns 0 for no matching documents', function () { + expect(Count::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)'))->toBe(0); + }); +}); diff --git a/tests/Integration/PostgreSQL/CustomTest.php b/tests/Integration/PostgreSQL/CustomTest.php new file mode 100644 index 0000000..44f34a3 --- /dev/null +++ b/tests/Integration/PostgreSQL/CustomTest.php @@ -0,0 +1,98 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Count, Custom, DocumentException, Query}; +use BitBadger\PDODocument\Mapper\{CountMapper, DocumentMapper}; +use Test\Integration\PostgreSQL\ThrowawayDb; +use Test\Integration\TestDocument; + +pest()->group('integration', 'postgresql'); + +describe('::runQuery()', function () { + test('runs a valid query successfully', function () { + $stmt = &Custom::runQuery('SELECT data FROM ' . ThrowawayDb::TABLE . ' LIMIT 1', []); + try { + expect($stmt)->not->toBeNull(); + } finally { + $stmt = null; + } + }); + test('fails with an invalid query', function () { + $stmt = null; + try { + expect(function () use (&$stmt) { $stmt = &Custom::runQuery('GRAB stuff FROM over_there UNTIL done', []); }) + ->toThrow(DocumentException::class); + } finally { + $stmt = null; + } + }); +}); + +describe('::list()', function () { + test('returns non-empty list when data found', function () { + $list = Custom::list(Query::selectFromTable(ThrowawayDb::TABLE), [], new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull(); + $count = 0; + foreach ($list->items() as $ignored) $count++; + expect($count)->toBe(5); + }); + test('returns empty list when no data found', function () { + expect(Custom::list( + Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric > :value", + [':value' => 100], new DocumentMapper(TestDocument::class))) + ->not->toBeNull() + ->hasItems()->toBeFalse(); + }); +}); + +describe('::array()', function () { + test('returns non-empty array when data found', function () { + expect(Custom::array(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'sub' IS NOT NULL", [], + new DocumentMapper(TestDocument::class))) + ->not->toBeNull() + ->toHaveCount(2); + }); + test('returns empty array when no data found', function () { + expect(Custom::array(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'value' = :value", + [':value' => 'not there'], new DocumentMapper(TestDocument::class))) + ->not->toBeNull() + ->toBeEmpty(); + }); +}); + +describe('::single()', function () { + test('returns a document when one is found', function () { + expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", [':id' => 'one'], + new DocumentMapper(TestDocument::class))) + ->isSome()->toBeTrue() + ->get()->id->toBe('one'); + }); + test('returns no document when one is not found', function () { + expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", + [':id' => 'eighty'], new DocumentMapper(TestDocument::class))) + ->isNone()->toBeTrue(); + }); +}); + +describe('::nonQuery()', function () { + test('works when documents match the WHERE clause', function () { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + expect(Count::all(ThrowawayDb::TABLE))->toBe(0); + }); + test('works when no documents match the WHERE clause', function () { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE . " WHERE (data->>'num_value')::numeric > :value", + [':value' => 100]); + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + }); +}); + +describe('::scalar()', function () { + test('returns a scalar value', function () { + expect(Custom::scalar("SELECT 5 AS it", [], new CountMapper()))->toBe(5); + }); +}); diff --git a/tests/Integration/PostgreSQL/DefinitionTest.php b/tests/Integration/PostgreSQL/DefinitionTest.php new file mode 100644 index 0000000..e01eb27 --- /dev/null +++ b/tests/Integration/PostgreSQL/DefinitionTest.php @@ -0,0 +1,47 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Definition, DocumentIndex}; + +pest()->group('integration', 'postgresql'); + +describe('::ensureTable()', function () { + test('creates a table', function () { + expect($this->dbObjectExists('ensured'))->toBeFalse() + ->and($this->dbObjectExists('idx_ensured_key'))->toBeFalse(); + Definition::ensureTable('ensured'); + expect($this->dbObjectExists('ensured'))->toBeTrue() + ->and($this->dbObjectExists('idx_ensured_key'))->toBeTrue(); + }); +}); + +describe('::ensureFieldIndex()', function () { + test('creates an index', function () { + expect($this->dbObjectExists('idx_ensured_test'))->toBeFalse(); + Definition::ensureTable('ensured'); + Definition::ensureFieldIndex('ensured', 'test', ['name', 'age']); + expect($this->dbObjectExists('idx_ensured_test'))->toBeTrue(); + }); +}); + +describe('::ensureDocumentIndex()', function () { + test('creates a full index', function () { + $docIdx = 'idx_doc_table_document'; + Definition::ensureTable('doc_table'); + expect($this->dbObjectExists($docIdx))->toBeFalse(); + Definition::ensureDocumentIndex('doc_table', DocumentIndex::Full); + expect($this->dbObjectExists($docIdx))->toBeTrue(); + }); + test('creates an optimized index', function () { + $docIdx = 'idx_doc_tbl_document'; + Definition::ensureTable('doc_tbl'); + expect($this->dbObjectExists($docIdx))->toBeFalse(); + Definition::ensureDocumentIndex('doc_tbl', DocumentIndex::Optimized); + expect($this->dbObjectExists($docIdx))->toBeTrue(); + }); +}); diff --git a/tests/Integration/PostgreSQL/DeleteTest.php b/tests/Integration/PostgreSQL/DeleteTest.php new file mode 100644 index 0000000..6d007e5 --- /dev/null +++ b/tests/Integration/PostgreSQL/DeleteTest.php @@ -0,0 +1,64 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Count, Delete, Field}; +use Test\Integration\PostgreSQL\ThrowawayDb; + +pest()->group('integration', 'postgresql'); + +describe('::byId()', function () { + test('deletes a document when ID is matched', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byId(ThrowawayDb::TABLE, 'four'); + expect(Count::all(ThrowawayDb::TABLE))->toBe(4); + }); + test('does not delete a document when ID is not matched', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byId(ThrowawayDb::TABLE, 'negative four'); + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + }); +}); + +describe('::byFields()', function () { + test('deletes documents when fields match', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byFields(ThrowawayDb::TABLE, [Field::notEqual('value', 'purple')]); + expect(Count::all(ThrowawayDb::TABLE))->toBe(2); + }); + test('does not delete documents when fields are not matched', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byFields(ThrowawayDb::TABLE, [Field::equal('value', 'crimson')]); + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + }); +}); + +describe('::byContains()', function () { + test('deletes documents when containment matches', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byContains(ThrowawayDb::TABLE, ['value' => 'purple']); + expect(Count::all(ThrowawayDb::TABLE))->toBe(3); + }); + test('does not delete documents when containment is not matched', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byContains(ThrowawayDb::TABLE, ['target' => 'acquired']); + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + }); +}); + +describe('::byJsonPath()', function () { + test('deletes documents when path matches', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ <> 0)'); + expect(Count::all(ThrowawayDb::TABLE))->toBe(1); + }); + test('does not delete documents when path is not matched', function () { + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + Delete::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ < 0)'); + expect(Count::all(ThrowawayDb::TABLE))->toBe(5); + }); +}); diff --git a/tests/Integration/PostgreSQL/DocumentListTest.php b/tests/Integration/PostgreSQL/DocumentListTest.php new file mode 100644 index 0000000..03cf339 --- /dev/null +++ b/tests/Integration/PostgreSQL/DocumentListTest.php @@ -0,0 +1,45 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{DocumentException, DocumentList, Query}; +use BitBadger\PDODocument\Mapper\DocumentMapper; +use Test\Integration\PostgreSQL\ThrowawayDb; +use Test\Integration\TestDocument; + +pest()->group('integration', 'postgresql'); + +describe('::create()', function () { + test('creates a document list', function () { + $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], + new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull(); + $list = null; // free database result + }); +}); + +describe('::items()', function () { + test('enumerates items in the list', function () { + $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], + new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull(); + $count = 0; + foreach ($list->items() as $item) { + expect(['one', 'two', 'three', 'four', 'five'])->toContain($item->id); + $count++; + } + expect($count)->toBe(5); + }); + test('fails when the list is exhausted', function () { + $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], + new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull()->hasItems()->toBeTrue(); + $ignored = iterator_to_array($list->items()); + expect($list)->hasItems()->toBeFalse() + ->and(fn () => iterator_to_array($list->items()))->toThrow(DocumentException::class); + }); +}); diff --git a/tests/Pest.php b/tests/Pest.php index 5a0e31f..26bbdc0 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -12,6 +12,7 @@ */ // pest()->extend(Tests\TestCase::class)->in('Feature'); +pest()->extend(Test\Integration\PgIntegrationTest::class)->in('Integration/PostgreSQL'); /* |-------------------------------------------------------------------------- diff --git a/tests/integration/postgresql/CountTest.php b/tests/integration/postgresql/CountTest.php deleted file mode 100644 index ccda872..0000000 --- a/tests/integration/postgresql/CountTest.php +++ /dev/null @@ -1,84 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Integration\PostgreSQL; - -use BitBadger\PDODocument\{Count, Field}; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * PostgreSQL integration tests for the Count class - */ -#[TestDox('Count (PostgreSQL integration)')] -class CountTest extends TestCase -{ - /** @var string Database name for throwaway database */ - private string $dbName; - - protected function setUp(): void - { - parent::setUp(); - $this->dbName = ThrowawayDb::create(); - } - - protected function tearDown(): void - { - ThrowawayDb::destroy($this->dbName); - parent::tearDown(); - } - - #[TestDox('all() succeeds')] - public function testAllSucceeds(): void - { - $count = Count::all(ThrowawayDb::TABLE); - $this->assertEquals(5, $count, 'There should have been 5 matching documents'); - } - - #[TestDox('byFields() succeeds for a numeric range')] - public function testByFieldsSucceedsForANumericRange(): void - { - $count = Count::byFields(ThrowawayDb::TABLE, [Field::between('num_value', 10, 20)]); - $this->assertEquals(3, $count, 'There should have been 3 matching documents'); - } - - #[TestDox('byFields() succeeds for a non-numeric range')] - public function testByFieldsSucceedsForANonNumericRange(): void - { - $count = Count::byFields(ThrowawayDb::TABLE, [Field::between('value', 'aardvark', 'apple')]); - $this->assertEquals(1, $count, 'There should have been 1 matching document'); - } - - #[TestDox('byContains() succeeds when documents match')] - public function testByContainsSucceedsWhenDocumentsMatch(): void - { - $this->assertEquals(2, Count::byContains(ThrowawayDb::TABLE, ['value' => 'purple']), - 'There should have been 2 matching documents'); - } - - #[TestDox('byContains() succeeds when no documents match')] - public function testByContainsSucceedsWhenNoDocumentsMatch(): void - { - $this->assertEquals(0, Count::byContains(ThrowawayDb::TABLE, ['value' => 'magenta']), - 'There should have been no matching documents'); - } - - #[TestDox('byJsonPath() succeeds when documents match')] - public function testByJsonPathSucceedsWhenDocumentsMatch(): void - { - $this->assertEquals(2, Count::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ < 5)'), - 'There should have been 2 matching documents'); - } - - #[TestDox('byJsonPath() succeeds when no documents match')] - public function testByJsonPathSucceedsWhenNoDocumentsMatch(): void - { - $this->assertEquals(0, Count::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)'), - 'There should have been no matching documents'); - } -} diff --git a/tests/integration/postgresql/CustomTest.php b/tests/integration/postgresql/CustomTest.php deleted file mode 100644 index a12b9d6..0000000 --- a/tests/integration/postgresql/CustomTest.php +++ /dev/null @@ -1,138 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Integration\PostgreSQL; - -use BitBadger\PDODocument\{Count, Custom, DocumentException, Query}; -use BitBadger\PDODocument\Mapper\{CountMapper, DocumentMapper}; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; -use Test\Integration\TestDocument; - -/** - * PostgreSQL integration tests for the Custom class - */ -#[TestDox('Custom (PostgreSQL integration)')] -class CustomTest extends TestCase -{ - /** @var string Database name for throwaway database */ - private string $dbName; - - public function setUp(): void - { - parent::setUp(); - $this->dbName = ThrowawayDb::create(); - } - - public function tearDown(): void - { - ThrowawayDb::destroy($this->dbName); - } - - #[TestDox('runQuery() succeeds with a valid query')] - public function testRunQuerySucceedsWithAValidQuery(): void - { - $stmt = &Custom::runQuery('SELECT data FROM ' . ThrowawayDb::TABLE . ' LIMIT 1', []); - try { - $this->assertNotNull($stmt, 'The statement should not have been null'); - } finally { - $stmt = null; - } - } - - #[TestDox('runQuery() fails with an invalid query')] - public function testRunQueryFailsWithAnInvalidQuery(): void - { - $this->expectException(DocumentException::class); - $stmt = &Custom::runQuery('GRAB stuff FROM over_there UNTIL done', []); - try { - $this->assertTrue(false, 'This code should not be reached'); - } finally { - $stmt = null; - } - } - - #[TestDox('list() succeeds when data is found')] - public function testListSucceedsWhenDataIsFound(): void - { - $list = Custom::list(Query::selectFromTable(ThrowawayDb::TABLE), [], new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'The document list should not be null'); - $count = 0; - foreach ($list->items() as $ignored) $count++; - $this->assertEquals(5, $count, 'There should have been 5 documents in the list'); - } - - #[TestDox('list() succeeds when no data is found')] - public function testListSucceedsWhenNoDataIsFound(): void - { - $list = Custom::list( - Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric > :value", - [':value' => 100], new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'The document list should not be null'); - $this->assertFalse($list->hasItems(), 'There should have been no documents in the list'); - } - - #[TestDox('array() succeeds when data is found')] - public function testArraySucceedsWhenDataIsFound(): void - { - $array = Custom::array(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'sub' IS NOT NULL", [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($array, 'The document array should not be null'); - $this->assertCount(2, $array, 'There should have been 2 documents in the array'); - } - - #[TestDox('array() succeeds when no data is found')] - public function testArraySucceedsWhenNoDataIsFound(): void - { - $array = Custom::array(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'value' = :value", - [':value' => 'not there'], new DocumentMapper(TestDocument::class)); - $this->assertNotNull($array, 'The document array should not be null'); - $this->assertCount(0, $array, 'There should have been no documents in the array'); - } - - #[TestDox('single() succeeds when a row is found')] - public function testSingleSucceedsWhenARowIsFound(): void - { - $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", [':id' => 'one'], - new DocumentMapper(TestDocument::class)); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals('one', $doc->get()->id, 'The incorrect document was returned'); - } - - #[TestDox('single() succeeds when a row is not found')] - public function testSingleSucceedsWhenARowIsNotFound(): void - { - $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", - [':id' => 'eighty'], new DocumentMapper(TestDocument::class)); - $this->assertTrue($doc->isNone(), 'There should not have been a document returned'); - } - - #[TestDox('nonQuery() succeeds when operating on data')] - public function testNonQuerySucceedsWhenOperatingOnData(): void - { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - $remaining = Count::all(ThrowawayDb::TABLE); - $this->assertEquals(0, $remaining, 'There should be no documents remaining in the table'); - } - - #[TestDox('nonQuery() succeeds when no data matches WHERE clause')] - public function testNonQuerySucceedsWhenNoDataMatchesWhereClause(): void - { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE . " WHERE (data->>'num_value')::numeric > :value", - [':value' => 100]); - $remaining = Count::all(ThrowawayDb::TABLE); - $this->assertEquals(5, $remaining, 'There should be 5 documents remaining in the table'); - } - - #[TestDox('scalar() succeeds')] - public function testScalarSucceeds(): void - { - $value = Custom::scalar("SELECT 5 AS it", [], new CountMapper()); - $this->assertEquals(5, $value, 'The scalar value was not returned correctly'); - } -} diff --git a/tests/integration/postgresql/DefinitionTest.php b/tests/integration/postgresql/DefinitionTest.php deleted file mode 100644 index 0aa7433..0000000 --- a/tests/integration/postgresql/DefinitionTest.php +++ /dev/null @@ -1,88 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Integration\PostgreSQL; - -use BitBadger\PDODocument\{Custom, Definition, DocumentException, DocumentIndex}; -use BitBadger\PDODocument\Mapper\ExistsMapper; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * PostgreSQL integration tests for the Definition class - */ -#[TestDox('Definition (PostgreSQL integration)')] -class DefinitionTest extends TestCase -{ - /** @var string Database name for throwaway database */ - private string $dbName; - - protected function setUp(): void - { - parent::setUp(); - $this->dbName = ThrowawayDb::create(withData: false); - } - - protected function tearDown(): void - { - ThrowawayDb::destroy($this->dbName); - parent::tearDown(); - } - - /** - * Does the given named object exist in the database? - * - * @param string $name The name of the object whose existence should be verified - * @return bool True if the object exists, false if not - * @throws DocumentException If any is encountered - */ - private function itExists(string $name): bool - { - return Custom::scalar('SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = :name)', - [':name' => $name], new ExistsMapper()); - } - - #[TestDox('ensureTable() succeeds')] - public function testEnsureTableSucceeds(): void - { - $this->assertFalse($this->itExists('ensured'), 'The table should not exist already'); - $this->assertFalse($this->itExists('idx_ensured_key'), 'The key index should not exist already'); - Definition::ensureTable('ensured'); - $this->assertTrue($this->itExists('ensured'), 'The table should now exist'); - $this->assertTrue($this->itExists('idx_ensured_key'), 'The key index should now exist'); - } - - #[TestDox('ensureFieldIndex() succeeds')] - public function testEnsureFieldIndexSucceeds(): void - { - $this->assertFalse($this->itExists('idx_ensured_test'), 'The index should not exist already'); - Definition::ensureTable('ensured'); - Definition::ensureFieldIndex('ensured', 'test', ['name', 'age']); - $this->assertTrue($this->itExists('idx_ensured_test'), 'The index should now exist'); - } - - #[TestDox('ensureDocumentIndex() succeeds for Full')] - public function testEnsureDocumentIndexSucceedsForFull(): void - { - $docIdx = 'idx_' . ThrowawayDb::TABLE . '_document'; - Definition::ensureTable(ThrowawayDb::TABLE); - $this->assertFalse($this->itExists($docIdx), 'The document index should not exist'); - Definition::ensureDocumentIndex(ThrowawayDb::TABLE, DocumentIndex::Full); - $this->assertTrue($this->itExists($docIdx), 'The document index should now exist'); - } - - #[TestDox('ensureDocumentIndex() succeeds for Optimized')] - public function testEnsureDocumentIndexSucceedsForOptimized(): void - { - $docIdx = 'idx_' . ThrowawayDb::TABLE . '_document'; - Definition::ensureTable(ThrowawayDb::TABLE); - $this->assertFalse($this->itExists($docIdx), 'The document index should not exist'); - Definition::ensureDocumentIndex(ThrowawayDb::TABLE, DocumentIndex::Optimized); - $this->assertTrue($this->itExists($docIdx), 'The document index should now exist'); - } -} diff --git a/tests/integration/postgresql/DeleteTest.php b/tests/integration/postgresql/DeleteTest.php deleted file mode 100644 index d354fe0..0000000 --- a/tests/integration/postgresql/DeleteTest.php +++ /dev/null @@ -1,99 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Integration\PostgreSQL; - -use BitBadger\PDODocument\{Count, Delete, Field}; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * PostgreSQL integration tests for the Delete class - */ -#[TestDox('Delete (PostgreSQL integration)')] -class DeleteTest extends TestCase -{ - /** @var string Database name for throwaway database */ - private string $dbName; - - protected function setUp(): void - { - parent::setUp(); - $this->dbName = ThrowawayDb::create(); - } - - protected function tearDown(): void - { - ThrowawayDb::destroy($this->dbName); - parent::tearDown(); - } - - #[TestDox('byId() succeeds when a document is deleted')] - public function testByIdSucceedsWhenADocumentIsDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byId(ThrowawayDb::TABLE, 'four'); - $this->assertEquals(4, Count::all(ThrowawayDb::TABLE), 'There should have been 4 documents remaining'); - } - - #[TestDox('byId() succeeds when a document is not deleted')] - public function testByIdSucceedsWhenADocumentIsNotDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byId(ThrowawayDb::TABLE, 'negative four'); - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents remaining'); - } - - #[TestDox('byFields() succeeds when documents are deleted')] - public function testByFieldsSucceedsWhenDocumentsAreDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byFields(ThrowawayDb::TABLE, [Field::notEqual('value', 'purple')]); - $this->assertEquals(2, Count::all(ThrowawayDb::TABLE), 'There should have been 2 documents remaining'); - } - - #[TestDox('byFields() succeeds when documents are not deleted')] - public function testByFieldsSucceedsWhenDocumentsAreNotDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byFields(ThrowawayDb::TABLE, [Field::equal('value', 'crimson')]); - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents remaining'); - } - - #[TestDox('byContains() succeeds when documents are deleted')] - public function testByContainsSucceedsWhenDocumentsAreDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byContains(ThrowawayDb::TABLE, ['value' => 'purple']); - $this->assertEquals(3, Count::all(ThrowawayDb::TABLE), 'There should have been 3 documents remaining'); - } - - #[TestDox('byContains() succeeds when documents are not deleted')] - public function testByContainsSucceedsWhenDocumentsAreNotDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byContains(ThrowawayDb::TABLE, ['target' => 'acquired']); - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents remaining'); - } - - #[TestDox('byJsonPath() succeeds when documents are deleted')] - public function testByJsonPathSucceedsWhenDocumentsAreDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ <> 0)'); - $this->assertEquals(1, Count::all(ThrowawayDb::TABLE), 'There should have been 1 document remaining'); - } - - #[TestDox('byJsonPath() succeeds when documents are not deleted')] - public function testByJsonPathSucceedsWhenDocumentsAreNotDeleted(): void - { - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents to start'); - Delete::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ < 0)'); - $this->assertEquals(5, Count::all(ThrowawayDb::TABLE), 'There should have been 5 documents remaining'); - } -} diff --git a/tests/integration/postgresql/ThrowawayDb.php b/tests/integration/postgresql/ThrowawayDb.php index 84e2049..c434f93 100644 --- a/tests/integration/postgresql/ThrowawayDb.php +++ b/tests/integration/postgresql/ThrowawayDb.php @@ -37,6 +37,20 @@ class ThrowawayDb Configuration::resetPDO(); } + /** + * Load data into the test table + * + * @throws DocumentException If any is encountered + */ + public static function loadData(): void + { + Document::insert(self::TABLE, new TestDocument('one', 'FIRST!', 0)); + Document::insert(self::TABLE, new TestDocument('two', 'another', 10, new SubDocument('green', 'blue'))); + Document::insert(self::TABLE, new TestDocument('three', '', 4)); + Document::insert(self::TABLE, new TestDocument('four', 'purple', 17, new SubDocument('green', 'red'))); + Document::insert(self::TABLE, new TestDocument('five', 'purple', 18)); + } + /** * Create a throwaway PostgreSQL database * @@ -51,13 +65,10 @@ class ThrowawayDb Custom::nonQuery("CREATE DATABASE $dbName WITH OWNER " . Configuration::$username, []); self::configure($dbName); + Definition::ensureTable(self::TABLE); + if ($withData) { - Definition::ensureTable(self::TABLE); - Document::insert(self::TABLE, new TestDocument('one', 'FIRST!', 0)); - Document::insert(self::TABLE, new TestDocument('two', 'another', 10, new SubDocument('green', 'blue'))); - Document::insert(self::TABLE, new TestDocument('three', '', 4)); - Document::insert(self::TABLE, new TestDocument('four', 'purple', 17, new SubDocument('green', 'red'))); - Document::insert(self::TABLE, new TestDocument('five', 'purple', 18)); + self::loadData(); } return $dbName;