From 9437dd37bf7d2dedc8f62b61b5fcbac6d92f34ba Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Fri, 15 Nov 2024 10:13:11 -0500 Subject: [PATCH] WIP on PostgreSQL integration tests --- .../PostgreSQL/DocumentListTest.php | 53 ++- tests/Integration/PostgreSQL/DocumentTest.php | 249 ++++++++++++++ .../postgresql/DocumentListTest.php | 135 -------- tests/integration/postgresql/DocumentTest.php | 319 ------------------ 4 files changed, 301 insertions(+), 455 deletions(-) create mode 100644 tests/Integration/PostgreSQL/DocumentTest.php delete mode 100644 tests/integration/postgresql/DocumentListTest.php delete mode 100644 tests/integration/postgresql/DocumentTest.php diff --git a/tests/Integration/PostgreSQL/DocumentListTest.php b/tests/Integration/PostgreSQL/DocumentListTest.php index 03cf339..0a22fe2 100644 --- a/tests/Integration/PostgreSQL/DocumentListTest.php +++ b/tests/Integration/PostgreSQL/DocumentListTest.php @@ -22,7 +22,7 @@ describe('::create()', function () { }); }); -describe('::items()', function () { +describe('->items()', function () { test('enumerates items in the list', function () { $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], new DocumentMapper(TestDocument::class)); @@ -43,3 +43,54 @@ describe('::items()', function () { ->and(fn () => iterator_to_array($list->items()))->toThrow(DocumentException::class); }); }); + +describe('->hasItems()', function () { + test('returns false when no items are in the list', function () { + expect(DocumentList::create( + Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric < 0", [], + new DocumentMapper(TestDocument::class))) + ->not->toBeNull() + ->hasItems()->toBeFalse(); + }); + test('returns true when items are in the list', function () { + $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], + new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull()->hasItems()->toBeTrue(); + foreach ($list->items() as $ignored) { + expect($list)->hasItems()->toBeTrue(); + } + expect($list)->hasItems()->toBeFalse(); + }); +}); + +describe('->map()', function () { + test('transforms the list', function () { + $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], + new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull()->hasItems()->toBeTrue(); + foreach ($list->map(fn($doc) => strrev($doc->id)) as $mapped) { + expect(['eno', 'owt', 'eerht', 'ruof', 'evif'])->toContain($mapped); + } + }); +}); + +describe('->iter()', function () { + test('walks the list', function () { + $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], + new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull()->hasItems()->toBeTrue(); + $splats = []; + $list->iter(function ($doc) use (&$splats) { $splats[] = str_repeat('*', strlen($doc->id)); }); + expect(implode(' ', $splats))->toBe('*** *** ***** **** ****'); + }); +}); + +describe('->mapToArray()', function () { + test('creates an associative array', function () { + $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], + new DocumentMapper(TestDocument::class)); + expect($list)->not->toBeNull()->hasItems()->toBeTrue() + ->and($list->mapToArray(fn($it) => $it->id, fn($it) => $it->value)) + ->toBe(['one' => 'FIRST!', 'two' => 'another', 'three' => '', 'four' => 'purple', 'five' => 'purple']); + }); +}); diff --git a/tests/Integration/PostgreSQL/DocumentTest.php b/tests/Integration/PostgreSQL/DocumentTest.php new file mode 100644 index 0000000..0c968b6 --- /dev/null +++ b/tests/Integration/PostgreSQL/DocumentTest.php @@ -0,0 +1,249 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{AutoId, Configuration, Custom, Document, DocumentException, Field, Find, Query}; +use BitBadger\PDODocument\Mapper\ArrayMapper; +use Test\Integration\PostgreSQL\ThrowawayDb; +use Test\Integration\{NumDocument, SubDocument, TestDocument}; + +pest()->group('integration', 'postgresql'); + +describe('::insert()', function () { + test('inserts an array with no automatic ID', function () { + Document::insert(ThrowawayDb::TABLE, ['id' => 'turkey', 'sub' => ['foo' => 'gobble', 'bar' => 'gobble']]); + $tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class); + expect($tryDoc) + ->isSome()->toBeTrue() + ->and($tryDoc->get()) + ->id->toBe('turkey') + ->value->toBe('') + ->num_value->toBe(0) + ->sub->not->toBeNull() + ->sub->foo->toBe('gobble') + ->sub->bar->toBe('gobble'); + }); + test('inserts an array with auto-number ID, not provided', function () { + Configuration::$autoId = AutoId::Number; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + + Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'new', 'num_value' => 8]); + $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper()); + expect($doc)->isSome()->toBeTrue() + ->and(json_decode($doc->get()['data'])) + ->id->toBe(1); + + Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'again', 'num_value' => 7]); + $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE " . Query::whereById(docId: 2), + [':id' => 2], new ArrayMapper()); + expect($doc)->isSome()->toBeTrue() + ->and(json_decode($doc->get()['data'])) + ->id->toBe(2); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an array with auto-number ID, provided', function () { + Configuration::$autoId = AutoId::Number; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, ['id' => 7, 'value' => 'new', 'num_value' => 8]); + $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper()); + expect($doc)->isSome()->toBeTrue() + ->and(json_decode($doc->get()['data'])) + ->id->toBe(7); + } finally { + Configuration::$autoId = AutoId::None; + } + + }); + test('inserts an array with auto-UUID ID, not provided', function () { + Configuration::$autoId = AutoId::UUID; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, ['id' => '', 'num_value' => 5]); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 5)], TestDocument::class); + expect($doc) + ->isSome()->toBeTrue() + ->and($doc->get())->id->not->toBeEmpty(); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an array with auto-UUID ID, provided', function () { + Configuration::$autoId = AutoId::UUID; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + $uuid = AutoId::generateUUID(); + Document::insert(ThrowawayDb::TABLE, ['id' => $uuid, 'value' => 'uuid', 'num_value' => 12]); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 12)], TestDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toBe($uuid); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an array with auto-string ID, not provided', function () { + Configuration::$autoId = AutoId::RandomString; + Configuration::$idStringLength = 6; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, ['id' => '', 'value' => 'new', 'num_value' => 8]); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 8)], TestDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toHaveLength(6); + } finally { + Configuration::$autoId = AutoId::None; + Configuration::$idStringLength = 16; + } + }); + test('inserts an array with auto-string ID, provided', function () { + Configuration::$autoId = AutoId::RandomString; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, ['id' => 'my-key', 'value' => 'old', 'num_value' => 3]); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toBe('my-key'); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an object with no automatic ID', function () { + Document::insert(ThrowawayDb::TABLE, new TestDocument('turkey', sub: new SubDocument('gobble', 'gobble'))); + $tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class); + expect($tryDoc)->isSome()->toBeTrue(); + $doc = $tryDoc->get(); + expect($doc) + ->id->toBe('turkey') + ->num_value->toBe(0) + ->sub->not->toBeNull() + ->sub->foo->toBe('gobble') + ->sub->bar->toBe('gobble') + ->and($doc->value)->toBe(''); + }); + test('inserts an object with auto-number ID, not provided', function () { + Configuration::$autoId = AutoId::Number; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + + Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'taco')); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'taco')], NumDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toBe(1); + + Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'burrito')); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'burrito')], NumDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toBe(2); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an object with auto-number ID, provided', function () { + Configuration::$autoId = AutoId::Number; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, new NumDocument(64, 'large')); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'large')], NumDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toBe(64); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an object with auto-UUID ID, not provided', function () { + Configuration::$autoId = AutoId::UUID; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, new TestDocument(value: 'something', num_value: 9)); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::exists('value')], TestDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->not->toBeEmpty(); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an object with auto-UUID ID, provided', function () { + Configuration::$autoId = AutoId::UUID; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + $uuid = AutoId::generateUUID(); + Document::insert(ThrowawayDb::TABLE, new TestDocument($uuid, num_value: 14)); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 14)], TestDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toBe($uuid); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('inserts an object with auto-string ID, not provided', function () { + Configuration::$autoId = AutoId::RandomString; + Configuration::$idStringLength = 40; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, new TestDocument(num_value: 55)); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 55)], TestDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toHaveLength(40); + } finally { + Configuration::$autoId = AutoId::None; + Configuration::$idStringLength = 16; + } + }); + test('inserts an object with auto-string ID, provided', function () { + Configuration::$autoId = AutoId::RandomString; + try { + Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); + Document::insert(ThrowawayDb::TABLE, new TestDocument('my-key', num_value: 3)); + $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class); + expect($doc)->isSome()->toBeTrue() + ->and($doc->get())->id->toBe('my-key'); + } finally { + Configuration::$autoId = AutoId::None; + } + }); + test('throws an exception for duplicate key', function () { + expect(fn () => Document::insert(ThrowawayDb::TABLE, new TestDocument('one'))) + ->toThrow(DocumentException::class); + }); +}); + +describe('::save()', function () { + test('inserts a new document', function () { + Document::save(ThrowawayDb::TABLE, new TestDocument('test', sub: new SubDocument('a', 'b'))); + expect(Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class))->isSome()->toBeTrue(); + }); + test('updates an existing document', function () { + Document::save(ThrowawayDb::TABLE, new TestDocument('two', num_value: 44)); + $tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class); + expect($tryDoc)->isSome()->toBeTrue() + ->and($tryDoc->get()) + ->num_value->toBe(44) + ->sub->toBeNull(); + }); +}); + +describe('::update()', function () { + test('replaces an existing document', function () { + Document::update(ThrowawayDb::TABLE, 'one', new TestDocument('one', 'howdy', 8, new SubDocument('y', 'z'))); + $tryDoc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class); + expect($tryDoc)->isSome()->toBeTrue(); + $doc = $tryDoc->get(); + expect($doc) + ->num_value->toBe(8) + ->sub->not->toBeNull() + ->sub->foo->toBe('y') + ->sub->bar->toBe('z') + ->and($doc->value)->toBe('howdy'); + }); + test('does nothing for a non-existent document', function () { + Document::update(ThrowawayDb::TABLE, 'two-hundred', new TestDocument('200')); + expect(Find::byId(ThrowawayDb::TABLE, 'two-hundred', TestDocument::class))->isNone()->toBeTrue(); + }); +}); diff --git a/tests/integration/postgresql/DocumentListTest.php b/tests/integration/postgresql/DocumentListTest.php deleted file mode 100644 index 827247b..0000000 --- a/tests/integration/postgresql/DocumentListTest.php +++ /dev/null @@ -1,135 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Integration\PostgreSQL; - -use BitBadger\PDODocument\{DocumentException, DocumentList, Query}; -use BitBadger\PDODocument\Mapper\DocumentMapper; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; -use Test\Integration\TestDocument; - -/** - * PostgreSQL integration tests for the DocumentList class - */ -#[TestDox('DocumentList (PostgreSQL integration)')] -class DocumentListTest 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('create() succeeds')] - public function testCreateSucceeds(): void - { - $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $list = null; - } - - #[TestDox('items() succeeds')] - public function testItemsSucceeds(): void - { - $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $count = 0; - foreach ($list->items() as $item) { - $this->assertContains($item->id, ['one', 'two', 'three', 'four', 'five'], - 'An unexpected document ID was returned'); - $count++; - } - $this->assertEquals(5, $count, 'There should have been 5 documents returned'); - } - - #[TestDox('items() fails when already consumed')] - public function testItemsFailsWhenAlreadyConsumed(): void - { - $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $this->assertTrue($list->hasItems(), 'There should be items in the list'); - $ignored = iterator_to_array($list->items()); - $this->assertFalse($list->hasItems(), 'The list should no longer have items'); - $this->expectException(DocumentException::class); - iterator_to_array($list->items()); - } - - #[TestDox('hasItems() succeeds with empty results')] - public function testHasItemsSucceedsWithEmptyResults(): void - { - $list = DocumentList::create( - Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric < 0", [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $this->assertFalse($list->hasItems(), 'There should be no items in the list'); - } - - #[TestDox('hasItems() succeeds with non-empty results')] - public function testHasItemsSucceedsWithNonEmptyResults(): void - { - $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $this->assertTrue($list->hasItems(), 'There should be items in the list'); - foreach ($list->items() as $ignored) { - $this->assertTrue($list->hasItems(), 'There should be items remaining in the list'); - } - $this->assertFalse($list->hasItems(), 'There should be no remaining items in the list'); - } - - #[TestDox('map() succeeds')] - public function testMapSucceeds(): void - { - $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $this->assertTrue($list->hasItems(), 'There should be items in the list'); - foreach ($list->map(fn($doc) => strrev($doc->id)) as $mapped) { - $this->assertContains($mapped, ['eno', 'owt', 'eerht', 'ruof', 'evif'], - 'An unexpected mapped value was returned'); - } - } - - #[TestDox('iter() succeeds')] - public function testIterSucceeds(): void - { - $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $this->assertTrue($list->hasItems(), 'There should be items in the list'); - $splats = []; - $list->iter(function ($doc) use (&$splats) { $splats[] = str_repeat('*', strlen($doc->id)); }); - $this->assertEquals('*** *** ***** **** ****', implode(' ', $splats), - 'Iteration did not have the expected result'); - } - - #[TestDox('mapToArray() succeeds')] - public function testMapToArraySucceeds(): void - { - $list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [], - new DocumentMapper(TestDocument::class)); - $this->assertNotNull($list, 'There should have been a document list created'); - $this->assertTrue($list->hasItems(), 'There should be items in the list'); - $lookup = $list->mapToArray(fn($it) => $it->id, fn($it) => $it->value); - $expected = ['one' => 'FIRST!', 'two' => 'another', 'three' => '', 'four' => 'purple', 'five' => 'purple']; - $this->assertEquals($expected, $lookup, 'The array was not mapped correctly'); - } -} diff --git a/tests/integration/postgresql/DocumentTest.php b/tests/integration/postgresql/DocumentTest.php deleted file mode 100644 index 0997b5a..0000000 --- a/tests/integration/postgresql/DocumentTest.php +++ /dev/null @@ -1,319 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Integration\PostgreSQL; - -use BitBadger\PDODocument\{AutoId, Configuration, Custom, Document, DocumentException, Field, Find, Query}; -use BitBadger\PDODocument\Mapper\ArrayMapper; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; -use Test\Integration\{NumDocument, SubDocument, TestDocument}; - -/** - * PostgreSQL integration tests for the Document class - */ -#[TestDox('Document (PostgreSQL integration)')] -class DocumentTest 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('insert() succeeds for array no auto ID')] - public function testInsertSucceedsForArrayNoAutoId(): void - { - Document::insert(ThrowawayDb::TABLE, ['id' => 'turkey', 'sub' => ['foo' => 'gobble', 'bar' => 'gobble']]); - $tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class); - $this->assertTrue($tryDoc->isSome(), 'There should have been a document inserted'); - $doc = $tryDoc->get(); - $this->assertEquals('turkey', $doc->id, 'The ID was incorrect'); - $this->assertEquals('', $doc->value, 'The value was incorrect'); - $this->assertEquals(0, $doc->num_value, 'The numeric value was incorrect'); - $this->assertNotNull($doc->sub, 'The sub-document should not have been null'); - $this->assertEquals('gobble', $doc->sub->foo, 'The sub-document foo property was incorrect'); - $this->assertEquals('gobble', $doc->sub->bar, 'The sub-document bar property was incorrect'); - } - - #[TestDox('insert() succeeds for array with auto number ID not provided')] - public function testInsertSucceedsForArrayWithAutoNumberIdNotProvided(): void - { - Configuration::$autoId = AutoId::Number; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - - Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'new', 'num_value' => 8]); - $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper()); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $obj = json_decode($doc->get()['data']); - $this->assertEquals(1, $obj->id, 'The ID 1 should have been auto-generated'); - - Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'again', 'num_value' => 7]); - $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE " . Query::whereById(docId: 2), - [':id' => 2], new ArrayMapper()); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $obj = json_decode($doc->get()['data']); - $this->assertEquals(2, $obj->id, 'The ID 2 should have been auto-generated'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for array with auto number ID with ID provided')] - public function testInsertSucceedsForArrayWithAutoNumberIdWithIdProvided(): void - { - Configuration::$autoId = AutoId::Number; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, ['id' => 7, 'value' => 'new', 'num_value' => 8]); - $doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper()); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $obj = json_decode($doc->get()['data']); - $this->assertEquals(7, $obj->id, 'The ID 7 should have been stored'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for array with auto UUID ID not provided')] - public function testInsertSucceedsForArrayWithAutoUuidIdNotProvided(): void - { - Configuration::$autoId = AutoId::UUID; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, ['id' => '', 'num_value' => 5]); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 5)], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertNotEmpty($doc->get()->id, 'The ID should have been auto-generated'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for array with auto UUID ID with ID provided')] - public function testInsertSucceedsForArrayWithAutoUuidIdWithIdProvided(): void - { - Configuration::$autoId = AutoId::UUID; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - $uuid = AutoId::generateUUID(); - Document::insert(ThrowawayDb::TABLE, ['id' => $uuid, 'value' => 'uuid', 'num_value' => 12]); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 12)], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals($uuid, $doc->get()->id, 'The ID should not have been changed'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for array with auto string ID not provided')] - public function testInsertSucceedsForArrayWithAutoStringIdNotProvided(): void - { - Configuration::$autoId = AutoId::RandomString; - Configuration::$idStringLength = 6; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, ['id' => '', 'value' => 'new', 'num_value' => 8]); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 8)], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals(6, strlen($doc->get()->id), - 'The ID should have been auto-generated and had 6 characters'); - } finally { - Configuration::$autoId = AutoId::None; - Configuration::$idStringLength = 16; - } - } - - #[TestDox('insert() succeeds for array with auto string ID with ID provided')] - public function testInsertSucceedsForArrayWithAutoStringIdWithIdProvided(): void - { - Configuration::$autoId = AutoId::RandomString; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, ['id' => 'my-key', 'value' => 'old', 'num_value' => 3]); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals('my-key', $doc->get()->id, 'The ID should not have been changed'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for object no auto ID')] - public function testInsertSucceedsForObjectNoAutoId(): void - { - Document::insert(ThrowawayDb::TABLE, new TestDocument('turkey', sub: new SubDocument('gobble', 'gobble'))); - $tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class); - $this->assertTrue($tryDoc->isSome(), 'There should have been a document inserted'); - $doc = $tryDoc->get(); - $this->assertEquals('turkey', $doc->id, 'The ID was incorrect'); - $this->assertEquals('', $doc->value, 'The value was incorrect'); - $this->assertEquals(0, $doc->num_value, 'The numeric value was incorrect'); - $this->assertNotNull($doc->sub, 'The sub-document should not have been null'); - $this->assertEquals('gobble', $doc->sub->foo, 'The sub-document foo property was incorrect'); - $this->assertEquals('gobble', $doc->sub->bar, 'The sub-document bar property was incorrect'); - } - - #[TestDox('insert() succeeds for object with auto number ID not provided')] - public function testInsertSucceedsForObjectWithAutoNumberIdNotProvided(): void - { - Configuration::$autoId = AutoId::Number; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - - Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'taco')); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'taco')], NumDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals(1, $doc->get()->id, 'The ID 1 should have been auto-generated'); - - Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'burrito')); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'burrito')], NumDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals(2, $doc->get()->id, 'The ID 2 should have been auto-generated'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for object with auto number ID with ID provided')] - public function testInsertSucceedsForObjectWithAutoNumberIdWithIdProvided(): void - { - Configuration::$autoId = AutoId::Number; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, new NumDocument(64, 'large')); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'large')], NumDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals(64, $doc->get()->id, 'The ID 64 should have been stored'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for object with auto UUID ID not provided')] - public function testInsertSucceedsForObjectWithAutoUuidIdNotProvided(): void - { - Configuration::$autoId = AutoId::UUID; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, new TestDocument(value: 'something', num_value: 9)); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::exists('value')], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertNotEmpty($doc->get()->id, 'The ID should have been auto-generated'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for object with auto UUID ID with ID provided')] - public function testInsertSucceedsForObjectWithAutoUuidIdWithIdProvided(): void - { - Configuration::$autoId = AutoId::UUID; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - $uuid = AutoId::generateUUID(); - Document::insert(ThrowawayDb::TABLE, new TestDocument($uuid, num_value: 14)); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 14)], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals($uuid, $doc->get()->id, 'The ID should not have been changed'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() succeeds for object with auto string ID not provided')] - public function testInsertSucceedsForObjectWithAutoStringIdNotProvided(): void - { - Configuration::$autoId = AutoId::RandomString; - Configuration::$idStringLength = 40; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, new TestDocument(num_value: 55)); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 55)], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals(40, strlen($doc->get()->id), - 'The ID should have been auto-generated and had 40 characters'); - } finally { - Configuration::$autoId = AutoId::None; - Configuration::$idStringLength = 16; - } - } - - #[TestDox('insert() succeeds for object with auto string ID with ID provided')] - public function testInsertSucceedsForObjectWithAutoStringIdWithIdProvided(): void - { - Configuration::$autoId = AutoId::RandomString; - try { - Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []); - Document::insert(ThrowawayDb::TABLE, new TestDocument('my-key', num_value: 3)); - $doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - $this->assertEquals('my-key', $doc->get()->id, 'The ID should not have been changed'); - } finally { - Configuration::$autoId = AutoId::None; - } - } - - #[TestDox('insert() fails for duplicate key')] - public function testInsertFailsForDuplicateKey(): void - { - $this->expectException(DocumentException::class); - Document::insert(ThrowawayDb::TABLE, new TestDocument('one')); - } - - #[TestDox('save() succeeds when a document is inserted')] - public function testSaveSucceedsWhenADocumentIsInserted(): void - { - Document::save(ThrowawayDb::TABLE, new TestDocument('test', sub: new SubDocument('a', 'b'))); - $doc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class); - $this->assertTrue($doc->isSome(), 'There should have been a document returned'); - } - - #[TestDox('save() succeeds when a document is updated')] - public function testSaveSucceedsWhenADocumentIsUpdated(): void - { - Document::save(ThrowawayDb::TABLE, new TestDocument('two', num_value: 44)); - $tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class); - $this->assertTrue($tryDoc->isSome(), 'There should have been a document returned'); - $doc = $tryDoc->get(); - $this->assertEquals(44, $doc->num_value, 'The numeric value was not updated'); - $this->assertNull($doc->sub, 'The sub-document should have been null'); - } - - #[TestDox('update() succeeds when replacing a document')] - public function testUpdateSucceedsWhenReplacingADocument(): void - { - Document::update(ThrowawayDb::TABLE, 'one', new TestDocument('one', 'howdy', 8, new SubDocument('y', 'z'))); - $tryDoc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class); - $this->assertNotFalse($tryDoc->isSome(), 'There should have been a document returned'); - $doc = $tryDoc->get(); - $this->assertEquals('howdy', $doc->value, 'The value was incorrect'); - $this->assertEquals(8, $doc->num_value, 'The numeric value was incorrect'); - $this->assertNotNull($doc->sub, 'The sub-document should not have been null'); - $this->assertEquals('y', $doc->sub->foo, 'The sub-document foo property was incorrect'); - $this->assertEquals('z', $doc->sub->bar, 'The sub-document bar property was incorrect'); - } - - #[TestDox('update() succeeds when no document is replaced')] - public function testUpdateSucceedsWhenNoDocumentIsReplaced(): void - { - Document::update(ThrowawayDb::TABLE, 'two-hundred', new TestDocument('200')); - $doc = Find::byId(ThrowawayDb::TABLE, 'two-hundred', TestDocument::class); - $this->assertTrue($doc->isNone(), 'There should not have been a document returned'); - } -}