diff --git a/tests/Unit/Query/CountTest.php b/tests/Unit/Query/CountTest.php new file mode 100644 index 0000000..25f8cd9 --- /dev/null +++ b/tests/Unit/Query/CountTest.php @@ -0,0 +1,51 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; +use BitBadger\PDODocument\Query\Count; + +pest()->group('unit'); + +afterEach(function () { Configuration::overrideMode(null); }); + +describe('::all()', function () { + test('generates the correct SQL', function () { + expect(Count::all('a_table'))->toBe('SELECT COUNT(*) FROM a_table'); + }); +}); + +describe('::byFields()', function () { + test('generates the correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Count::byFields('somewhere', [Field::greater('errors', 10, ':errors')])) + ->toBe("SELECT COUNT(*) FROM somewhere WHERE data->>'errors' > :errors"); + }); +}); + +describe('::byContains()', function () { + test('generates the correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Count::byContains('the_table'))->toBe('SELECT COUNT(*) FROM the_table WHERE data @> :criteria'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Count::byContains(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); + +describe('::byJsonPath()', function () { + test('generates the correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Count::byJsonPath('a_table')) + ->toBe('SELECT COUNT(*) FROM a_table WHERE jsonb_path_exists(data, :path::jsonpath)'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Count::byJsonPath(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); diff --git a/tests/Unit/Query/DefinitionTest.php b/tests/Unit/Query/DefinitionTest.php new file mode 100644 index 0000000..d182422 --- /dev/null +++ b/tests/Unit/Query/DefinitionTest.php @@ -0,0 +1,65 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, DocumentIndex, Mode}; +use BitBadger\PDODocument\Query\Definition; + +pest()->group('unit'); + +describe('::ensureTable()', function () { + afterEach(function () { Configuration::overrideMode(null); }); + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Definition::ensureTable('documents')) + ->toBe('CREATE TABLE IF NOT EXISTS documents (data JSONB NOT NULL)'); + })->group('postgresql'); + test('generates correct SQL [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Definition::ensureTable('dox'))->toBe('CREATE TABLE IF NOT EXISTS dox (data TEXT NOT NULL)'); + })->group('sqlite'); + test('throws an exception if mode is not set', function () { + expect(fn () => Definition::ensureTable(''))->toThrow(DocumentException::class); + }); +}); + +describe('::ensureIndexOn()', function () { + test('generates correct SQL for unqualified table, single ascending field', function () { + expect(Definition::ensureIndexOn('test', 'fields', ['details'])) + ->toBe("CREATE INDEX IF NOT EXISTS idx_test_fields ON test ((data->>'details'))"); + }); + test('generates correct SQL for qualified table, multiple fields', function () { + expect(Definition::ensureIndexOn('sch.testing', 'json', ['group', 'sub_group DESC'])) + ->toBe('CREATE INDEX IF NOT EXISTS idx_testing_json ON sch.testing ' + . "((data->>'group'), (data->>'sub_group') DESC)"); + }); +}); + +describe('::ensureKey()', function () { + test('generates correct SQL', function () { + expect(Definition::ensureKey('tbl')) + ->toBe("CREATE UNIQUE INDEX IF NOT EXISTS idx_tbl_key ON tbl ((data->>'id'))"); + }); +}); + +describe('::ensureDocumentIndexOn()', function () { + afterEach(function () { Configuration::overrideMode(null); }); + test('generates correct SQL for qualified table, full index [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Definition::ensureDocumentIndexOn('my.tbl', DocumentIndex::Full)) + ->toBe("CREATE INDEX IF NOT EXISTS idx_tbl_document ON my.tbl USING GIN (data)"); + })->group('postgresql'); + test('generates correct SQL for unqualified table, optimized index [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Definition::ensureDocumentIndexOn('it', DocumentIndex::Optimized)) + ->toBe("CREATE INDEX IF NOT EXISTS idx_it_document ON it USING GIN (data jsonb_path_ops)"); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Definition::ensureDocumentIndexOn('', DocumentIndex::Full))->toThrow(DocumentException::class); + })->group('sqlite'); +}); diff --git a/tests/Unit/Query/DeleteTest.php b/tests/Unit/Query/DeleteTest.php new file mode 100644 index 0000000..7a95360 --- /dev/null +++ b/tests/Unit/Query/DeleteTest.php @@ -0,0 +1,52 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; +use BitBadger\PDODocument\Query\Delete; + +pest()->group('unit'); + +afterEach(function () { Configuration::overrideMode(null); }); + +describe('::byId()', function () { + test('generates correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Delete::byId('over_there'))->toBe("DELETE FROM over_there WHERE data->>'id' = :id"); + }); +}); + +describe('::byFields()', function () { + test('generates correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Delete::byFields('my_table', + [Field::less('value', 99, ':max'), Field::greaterOrEqual('value', 18, ':min')])) + ->toBe("DELETE FROM my_table WHERE data->>'value' < :max AND data->>'value' >= :min"); + }); +}); + +describe('::byContains()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Delete::byContains('somewhere'))->toBe('DELETE FROM somewhere WHERE data @> :criteria'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Delete::byContains(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); + +describe('::byJsonPath()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Delete::byJsonPath('here'))->toBe('DELETE FROM here WHERE jsonb_path_exists(data, :path::jsonpath)'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Delete::byJsonPath(''))->toThrow(DocumentException::class); + }); +}); diff --git a/tests/Unit/Query/ExistsTest.php b/tests/Unit/Query/ExistsTest.php new file mode 100644 index 0000000..216c312 --- /dev/null +++ b/tests/Unit/Query/ExistsTest.php @@ -0,0 +1,59 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; +use BitBadger\PDODocument\Query\Exists; + +pest()->group('unit'); + +afterEach(function () { Configuration::overrideMode(null); }); + +describe('::query()', function () { + test('generates correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Exists::query('abc', 'def'))->toBe('SELECT EXISTS (SELECT 1 FROM abc WHERE def)'); + }); +}); + +describe('::byId()', function () { + test('generates correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Exists::byId('dox'))->toBe("SELECT EXISTS (SELECT 1 FROM dox WHERE data->>'id' = :id)"); + }); +}); + +describe('::byFields()', function () { + test('generates correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Exists::byFields('box', [Field::notEqual('status', 'occupied', ':status')])) + ->toBe("SELECT EXISTS (SELECT 1 FROM box WHERE data->>'status' <> :status)"); + }); +}); + +describe('::byContains()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Exists::byContains('pocket'))->toBe('SELECT EXISTS (SELECT 1 FROM pocket WHERE data @> :criteria)'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Exists::byContains(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); + +describe('::byJsonPath()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Exists::byJsonPath('lint')) + ->toBe('SELECT EXISTS (SELECT 1 FROM lint WHERE jsonb_path_exists(data, :path::jsonpath))'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Exists::byJsonPath(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); diff --git a/tests/Unit/Query/FindTest.php b/tests/Unit/Query/FindTest.php new file mode 100644 index 0000000..a5e1dcc --- /dev/null +++ b/tests/Unit/Query/FindTest.php @@ -0,0 +1,53 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, Field, FieldMatch, Mode}; +use BitBadger\PDODocument\Query\Find; + +pest()->group('unit'); + +afterEach(function () { Configuration::overrideMode(null); }); + +describe('::byId()', function () { + test('generates correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Find::byId('here'))->toBe("SELECT data FROM here WHERE data->>'id' = :id"); + }); +}); + +describe('::byFields()', function () { + test('generates correct SQL', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Find::byFields('there', [Field::equal('active', true, ':act'), Field::equal('locked', true, ':lock')], + FieldMatch::Any)) + ->toBe("SELECT data FROM there WHERE data->>'active' = :act OR data->>'locked' = :lock"); + }); +}); + +describe('::byContains()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Find::byContains('disc'))->toBe('SELECT data FROM disc WHERE data @> :criteria'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Find::byContains(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); + +describe('::byJsonPath()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Find::byJsonPath('light')) + ->toBe('SELECT data FROM light WHERE jsonb_path_exists(data, :path::jsonpath)'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Find::byJsonPath(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); diff --git a/tests/Unit/Query/PatchTest.php b/tests/Unit/Query/PatchTest.php new file mode 100644 index 0000000..c1a4e6e --- /dev/null +++ b/tests/Unit/Query/PatchTest.php @@ -0,0 +1,68 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; +use BitBadger\PDODocument\Query\Patch; + +pest()->group('unit'); + +afterEach(function () { Configuration::overrideMode(null); }); + +describe('::byId()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Patch::byId('doc_table'))->toBe("UPDATE doc_table SET data = data || :data WHERE data->>'id' = :id"); + })->group('postgresql'); + test('generates correct SQL [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Patch::byId('my_table')) + ->toBe("UPDATE my_table SET data = json_patch(data, json(:data)) WHERE data->>'id' = :id"); + })->group('sqlite'); + test('throws an exception [mode not set]', function () { + expect(fn () => Patch::byId(''))->toThrow(DocumentException::class); + }); +}); + +describe('::byFields()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Patch::byFields('that', [Field::less('something', 17, ':some')])) + ->toBe("UPDATE that SET data = data || :data WHERE (data->>'something')::numeric < :some"); + })->group('postgresql'); + test('generates correct SQL [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(Patch::byFields('a_table', [Field::greater('something', 17, ':it')])) + ->toBe("UPDATE a_table SET data = json_patch(data, json(:data)) WHERE data->>'something' > :it"); + })->group('sqlite'); + test('throws an exception [mode not set]', function () { + expect(fn () => Patch::byFields('', []))->toThrow(DocumentException::class); + }); +}); + +describe('::byContains()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Patch::byContains('this'))->toBe('UPDATE this SET data = data || :data WHERE data @> :criteria'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Patch::byContains(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); + +describe('::byJsonPath()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(Patch::byJsonPath('that')) + ->toBe('UPDATE that SET data = data || :data WHERE jsonb_path_exists(data, :path::jsonpath)'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(fn () => Patch::byJsonPath(''))->toThrow(DocumentException::class); + })->group('sqlite'); +}); diff --git a/tests/Unit/Query/RemoveFieldsTest.php b/tests/Unit/Query/RemoveFieldsTest.php new file mode 100644 index 0000000..5b96fb5 --- /dev/null +++ b/tests/Unit/Query/RemoveFieldsTest.php @@ -0,0 +1,86 @@ + + * @license MIT + */ + +declare(strict_types=1); + +use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Parameters}; +use BitBadger\PDODocument\Query\RemoveFields; + +pest()->group('unit'); + +afterEach(function () { Configuration::overrideMode(null); }); + +describe('::update()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(RemoveFields::update('taco', [':names' => "{one,two}"], 'it = true')) + ->toBe('UPDATE taco SET data = data - :names::text[] WHERE it = true'); + })->group('postgresql'); + test('generates correct SQL [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(RemoveFields::update('burrito', Parameters::fieldNames(':name', ['one', 'two', 'ten']), 'a = b')) + ->toBe('UPDATE burrito SET data = json_remove(data, :name0, :name1, :name2) WHERE a = b'); + })->group('sqlite'); + test('throws an exception [mode not set]', function () { + expect(fn () => RemoveFields::update('', [], ''))->toThrow(DocumentException::class); + }); +}); + +describe('::byId()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(RemoveFields::byId('churro', Parameters::fieldNames(':bite', ['byte']))) + ->toBe("UPDATE churro SET data = data - :bite::text[] WHERE data->>'id' = :id"); + })->group('postgresql'); + test('generates correct SQL [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(RemoveFields::byId('quesadilla', Parameters::fieldNames(':bite', ['byte']))) + ->toBe("UPDATE quesadilla SET data = json_remove(data, :bite0) WHERE data->>'id' = :id"); + })->group('sqlite'); + test('throws an exception [mode not set]', function () { + expect(fn () => RemoveFields::byId('', []))->toThrow(DocumentException::class); + }); +}); + +describe('::byFields()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(RemoveFields::byFields('enchilada', [Field::equal('cheese', 'jack', ':queso')], + Parameters::fieldNames(':sauce', ['white']))) + ->toBe("UPDATE enchilada SET data = data - :sauce::text[] WHERE data->>'cheese' = :queso"); + })->group('postgresql'); + test('generates correct SQL [SQLite]', function () { + Configuration::overrideMode(Mode::SQLite); + expect(RemoveFields::byFields('chimichanga', [Field::equal('side', 'beans', ':rice')], + Parameters::fieldNames(':filling', ['beef']))) + ->toBe("UPDATE chimichanga SET data = json_remove(data, :filling0) WHERE data->>'side' = :rice"); + })->group('sqlite'); + test('throws an exception [mode not set]', function () { + expect(fn () => RemoveFields::byFields('', [], []))->toThrow(DocumentException::class); + }); +}); + +describe('::byContains()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(RemoveFields::byContains('food', Parameters::fieldNames(':drink', ['a', 'b']))) + ->toBe('UPDATE food SET data = data - :drink::text[] WHERE data @> :criteria'); + })->group('postgresql'); + test('throws an exception [SQLite]', function () { + expect(fn () => RemoveFields::byContains('', []))->toThrow(DocumentException::class); + })->group('sqlite'); +}); + +describe('::byJsonPath()', function () { + test('generates correct SQL [PostgreSQL]', function () { + Configuration::overrideMode(Mode::PgSQL); + expect(RemoveFields::byJsonPath('dessert', Parameters::fieldNames(':cake', ['b', 'c']))) + ->toBe('UPDATE dessert SET data = data - :cake::text[] WHERE jsonb_path_exists(data, :path::jsonpath)'); + }); + test('throws an exception [SQLite]', function () { + expect(fn () => RemoveFields::byJsonPath('', []))->toThrow(DocumentException::class); + })->group('sqlite'); +}); diff --git a/tests/unit/Query/CountTest.php b/tests/unit/Query/CountTest.php deleted file mode 100644 index cdad3ac..0000000 --- a/tests/unit/Query/CountTest.php +++ /dev/null @@ -1,73 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit\Query; - -use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; -use BitBadger\PDODocument\Query\Count; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Count class - */ -#[TestDox('Count Queries (Unit tests)')] -class CountTest extends TestCase -{ - public function tearDown(): void - { - Configuration::overrideMode(null); - parent::tearDown(); - } - - #[TestDox('all() succeeds')] - public function testAllSucceeds(): void - { - $this->assertEquals('SELECT COUNT(*) FROM a_table', Count::all('a_table'), - 'SELECT statement not generated correctly'); - } - - #[TestDox('byFields() succeeds')] - public function testByFieldsSucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("SELECT COUNT(*) FROM somewhere WHERE data->>'errors' > :errors", - Count::byFields('somewhere', [Field::greater('errors', 10, ':errors')]), - 'SELECT statement not generated correctly'); - } - - #[TestDox('byContains() succeeds for PostgreSQL')] - public function testByContainsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('SELECT COUNT(*) FROM the_table WHERE data @> :criteria', Count::byContains('the_table'), - 'SELECT statement not generated correctly'); - } - - #[TestDox('byContains() fails for non PostgreSQL')] - public function testByContainsFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Count::byContains(''); - } - - #[TestDox('byJsonPath() succeeds for PostgreSQL')] - public function testByJsonPathSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('SELECT COUNT(*) FROM a_table WHERE jsonb_path_exists(data, :path::jsonpath)', - Count::byJsonPath('a_table'), 'SELECT statement not generated correctly'); - } - - #[TestDox('byJsonPath() fails for non PostgreSQL')] - public function testByJsonPathFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Count::byJsonPath(''); - } -} diff --git a/tests/unit/Query/DefinitionTest.php b/tests/unit/Query/DefinitionTest.php deleted file mode 100644 index 3af4c42..0000000 --- a/tests/unit/Query/DefinitionTest.php +++ /dev/null @@ -1,96 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit\Query; - -use BitBadger\PDODocument\{Configuration, DocumentException, DocumentIndex, Mode}; -use BitBadger\PDODocument\Query\Definition; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Definition class - */ -#[TestDox('Definition Queries (Unit tests)')] -class DefinitionTest extends TestCase -{ - protected function tearDown(): void - { - Configuration::overrideMode(null); - parent::tearDown(); - } - - #[TestDox('ensureTable() succeeds for PosgtreSQL')] - public function testEnsureTableSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('CREATE TABLE IF NOT EXISTS documents (data JSONB NOT NULL)', - Definition::ensureTable('documents'), 'CREATE TABLE statement not generated correctly'); - } - - #[TestDox('ensureTable() succeeds for SQLite')] - public function testEnsureTableSucceedsForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals('CREATE TABLE IF NOT EXISTS dox (data TEXT NOT NULL)', Definition::ensureTable('dox'), - 'CREATE TABLE statement not generated correctly'); - } - - #[TestDox('ensureTable() fails when mode not set')] - public function testEnsureTableFailsWhenModeNotSet(): void - { - $this->expectException(DocumentException::class); - Definition::ensureTable('boom'); - } - - #[TestDox('ensureIndexOn() succeeds without schema single ascending field')] - public function testEnsureIndexOnSucceedsWithoutSchemaSingleAscendingField(): void - { - $this->assertEquals("CREATE INDEX IF NOT EXISTS idx_test_fields ON test ((data->>'details'))", - Definition::ensureIndexOn('test', 'fields', ['details']), 'CREATE INDEX statement not generated correctly'); - } - - #[TestDox('ensureIndexOn() succeeds with schema multiple fields')] - public function testEnsureIndexOnSucceedsWithSchemaMultipleFields(): void - { - $this->assertEquals( - "CREATE INDEX IF NOT EXISTS idx_testing_json ON sch.testing ((data->>'group'), (data->>'sub_group') DESC)", - Definition::ensureIndexOn('sch.testing', 'json', ['group', 'sub_group DESC']), - 'CREATE INDEX statement not generated correctly'); - } - - #[TestDox('ensureKey() succeeds')] - public function testEnsureKeySucceeds(): void - { - $this->assertEquals("CREATE UNIQUE INDEX IF NOT EXISTS idx_tbl_key ON tbl ((data->>'id'))", - Definition::ensureKey('tbl'), 'CREATE INDEX statement for document key not generated correctly'); - } - - #[TestDox('ensureDocumentIndexOn() succeeds for schema and Full')] - public function testEnsureDocumentIndexOnSucceedsForSchemaAndFull(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals("CREATE INDEX IF NOT EXISTS idx_tbl_document ON my.tbl USING GIN (data)", - Definition::ensureDocumentIndexOn('my.tbl', DocumentIndex::Full)); - } - - #[TestDox('ensureDocumentIndexOn() succeeds for no schema and Optimized')] - public function testEnsureDocumentIndexOnSucceedsForNoSchemaAndOptimized(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals("CREATE INDEX IF NOT EXISTS idx_it_document ON it USING GIN (data jsonb_path_ops)", - Definition::ensureDocumentIndexOn('it', DocumentIndex::Optimized)); - } - - #[TestDox('ensureDocumentIndexOn() fails for non PostgreSQL')] - public function testEnsureDocumentIndexOnFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Definition::ensureDocumentIndexOn('', DocumentIndex::Full); - } -} diff --git a/tests/unit/Query/DeleteTest.php b/tests/unit/Query/DeleteTest.php deleted file mode 100644 index 0c3adce..0000000 --- a/tests/unit/Query/DeleteTest.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit\Query; - -use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; -use BitBadger\PDODocument\Query\Delete; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Delete class - */ -#[TestDox('Delete Queries (Unit tests)')] -class DeleteTest extends TestCase -{ - protected function tearDown(): void - { - Configuration::overrideMode(null); - } - - #[TestDox('byId() succeeds')] - public function testByIdSucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("DELETE FROM over_there WHERE data->>'id' = :id", Delete::byId('over_there'), - 'DELETE statement not constructed correctly'); - } - - #[TestDox('byFields() succeeds')] - public function testByFieldsSucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("DELETE FROM my_table WHERE data->>'value' < :max AND data->>'value' >= :min", - Delete::byFields('my_table', - [Field::less('value', 99, ':max'), Field::greaterOrEqual('value', 18, ':min')]), - 'DELETE statement not constructed correctly'); - } - - #[TestDox('byContains() succeeds for PostgreSQL')] - public function testByContainsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('DELETE FROM somewhere WHERE data @> :criteria', Delete::byContains('somewhere'), - 'DELETE statement not constructed correctly'); - } - - #[TestDox('byContains() fails for non PostgreSQL')] - public function testByContainsFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Delete::byContains(''); - } - - #[TestDox('byJsonPath() succeeds for PostgreSQL')] - public function testByJsonPathSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('DELETE FROM here WHERE jsonb_path_exists(data, :path::jsonpath)', - Delete::byJsonPath('here'), 'DELETE statement not constructed correctly'); - } - - #[TestDox('byJsonPath() fails for non PostgreSQL')] - public function testByJsonPathFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Delete::byJsonPath(''); - } -} diff --git a/tests/unit/Query/ExistsTest.php b/tests/unit/Query/ExistsTest.php deleted file mode 100644 index 1eb0fa4..0000000 --- a/tests/unit/Query/ExistsTest.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit\Query; - -use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; -use BitBadger\PDODocument\Query\Exists; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Exists class - */ -#[TestDox('Exists Queries (Unit tests)')] -class ExistsTest extends TestCase -{ - protected function tearDown(): void - { - Configuration::overrideMode(null); - } - - #[TestDox('query() succeeds')] - public function testQuerySucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals('SELECT EXISTS (SELECT 1 FROM abc WHERE def)', Exists::query('abc', 'def'), - 'Existence query not generated correctly'); - } - - #[TestDox('byId() succeeds')] - public function testByIdSucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("SELECT EXISTS (SELECT 1 FROM dox WHERE data->>'id' = :id)", Exists::byId('dox'), - 'Existence query not generated correctly'); - } - - #[TestDox('byFields() succeeds')] - public function testByFieldsSucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("SELECT EXISTS (SELECT 1 FROM box WHERE data->>'status' <> :status)", - Exists::byFields('box', [Field::notEqual('status', 'occupied', ':status')]), - 'Existence query not generated correctly'); - } - - #[TestDox('byContains() succeeds for PostgreSQL')] - public function testByContainsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('SELECT EXISTS (SELECT 1 FROM pocket WHERE data @> :criteria)', - Exists::byContains('pocket'), 'Existence query not generated correctly'); - } - - #[TestDox('byContains() fails for non PostgreSQL')] - public function testByContainsFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Exists::byContains(''); - } - - #[TestDox('byJsonPath() succeeds for PostgreSQL')] - public function testByJsonPathSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('SELECT EXISTS (SELECT 1 FROM lint WHERE jsonb_path_exists(data, :path::jsonpath))', - Exists::byJsonPath('lint'), 'Existence query not generated correctly'); - } - - #[TestDox('byJsonPath() fails for non PostgreSQL')] - public function testByJsonPathFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Exists::byJsonPath(''); - } -} diff --git a/tests/unit/Query/FindTest.php b/tests/unit/Query/FindTest.php deleted file mode 100644 index c1f471b..0000000 --- a/tests/unit/Query/FindTest.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit\Query; - -use BitBadger\PDODocument\{Configuration, DocumentException, Field, FieldMatch, Mode}; -use BitBadger\PDODocument\Query\Find; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Find class - */ -#[TestDox('Find Queries (Unit tests)')] -class FindTest extends TestCase -{ - protected function tearDown(): void - { - Configuration::overrideMode(null); - } - - #[TestDox('byId() succeeds')] - public function testByIdSucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("SELECT data FROM here WHERE data->>'id' = :id", Find::byId('here'), - 'SELECT query not generated correctly'); - } - - #[TestDox('byFields() succeeds')] - public function testByFieldsSucceeds(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("SELECT data FROM there WHERE data->>'active' = :act OR data->>'locked' = :lock", - Find::byFields('there', [Field::equal('active', true, ':act'), Field::equal('locked', true, ':lock')], - FieldMatch::Any), - 'SELECT query not generated correctly'); - } - - #[TestDox('byContains() succeeds for PostgreSQL')] - public function testByContainsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('SELECT data FROM disc WHERE data @> :criteria', Find::byContains('disc'), - 'SELECT query not generated correctly'); - } - - #[TestDox('byContains() fails for non PostgreSQL')] - public function testByContainsFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Find::byContains(''); - } - - #[TestDox('byJsonPath() succeeds for PostgreSQL')] - public function testByJsonPathSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('SELECT data FROM light WHERE jsonb_path_exists(data, :path::jsonpath)', - Find::byJsonPath('light'), 'SELECT query not generated correctly'); - } - - #[TestDox('byJsonPath() fails for non PostgreSQL')] - public function testByJsonPathFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Find::byJsonPath(''); - } -} diff --git a/tests/unit/Query/PatchTest.php b/tests/unit/Query/PatchTest.php deleted file mode 100644 index 415ff0c..0000000 --- a/tests/unit/Query/PatchTest.php +++ /dev/null @@ -1,104 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit\Query; - -use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode}; -use BitBadger\PDODocument\Query\Patch; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the Patch class - */ -#[TestDox('Patch Queries (Unit tests)')] -class PatchTest extends TestCase -{ - protected function tearDown(): void - { - Configuration::overrideMode(null); - parent::tearDown(); - } - #[TestDox('byId() succeeds for PostgreSQL')] - public function testByIdSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals("UPDATE doc_table SET data = data || :data WHERE data->>'id' = :id", - Patch::byId('doc_table'), 'Patch UPDATE statement is not correct'); - } - - #[TestDox('byId() succeeds for SQLite')] - public function testByIdSucceedsForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("UPDATE my_table SET data = json_patch(data, json(:data)) WHERE data->>'id' = :id", - Patch::byId('my_table'), 'Patch UPDATE statement is not correct'); - } - - #[TestDox('byId() fails when mode not set')] - public function testByIdFailsWhenModeNotSet(): void - { - $this->expectException(DocumentException::class); - Patch::byId('oof'); - } - - #[TestDox('byFields() succeeds for PostgreSQL')] - public function testByFieldsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals("UPDATE that SET data = data || :data WHERE (data->>'something')::numeric < :some", - Patch::byFields('that', [Field::less('something', 17, ':some')]), 'Patch UPDATE statement is not correct'); - } - - #[TestDox('byFields() succeeds for SQLite')] - public function testByFieldsSucceedsForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals( - "UPDATE a_table SET data = json_patch(data, json(:data)) WHERE data->>'something' > :it", - Patch::byFields('a_table', [Field::greater('something', 17, ':it')]), - 'Patch UPDATE statement is not correct'); - } - - #[TestDox('byFields() fails when mode not set')] - public function testByFieldsFailsWhenModeNotSet(): void - { - $this->expectException(DocumentException::class); - Patch::byFields('oops', []); - } - - #[TestDox('byContains() succeeds for PostgreSQL')] - public function testByContainsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('UPDATE this SET data = data || :data WHERE data @> :criteria', Patch::byContains('this'), - 'Patch UPDATE statement is not correct'); - } - - #[TestDox('byContains() fails for non PostgreSQL')] - public function testByContainsFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Patch::byContains(''); - } - - #[TestDox('byJsonPath() succeeds for PostgreSQL')] - public function testByJsonPathSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('UPDATE that SET data = data || :data WHERE jsonb_path_exists(data, :path::jsonpath)', - Patch::byJsonPath('that'), 'Patch UPDATE statement is not correct'); - } - - #[TestDox('byJsonPath() fails for non PostgreSQL')] - public function testByJsonPathFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - Patch::byJsonPath(''); - } -} diff --git a/tests/unit/Query/RemoveFieldsTest.php b/tests/unit/Query/RemoveFieldsTest.php deleted file mode 100644 index 7f8d0a9..0000000 --- a/tests/unit/Query/RemoveFieldsTest.php +++ /dev/null @@ -1,135 +0,0 @@ - - * @license MIT - */ - -declare(strict_types=1); - -namespace Test\Unit\Query; - -use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Parameters}; -use BitBadger\PDODocument\Query\RemoveFields; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\TestCase; - -/** - * Unit tests for the RemoveFields class - */ -#[TestDox('Remove Fields Queries (Unit tests)')] -class RemoveFieldsTest extends TestCase -{ - protected function tearDown(): void - { - Configuration::overrideMode(null); - } - - #[TestDox('update() succeeds for PostgreSQL')] - public function testUpdateSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('UPDATE taco SET data = data - :names::text[] WHERE it = true', - RemoveFields::update('taco', [':names' => "{one,two}"], 'it = true'), 'UPDATE statement not correct'); - } - - #[TestDox('update() succeeds for SQLite')] - public function testUpdateSucceedsForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals('UPDATE burrito SET data = json_remove(data, :name0, :name1, :name2) WHERE a = b', - RemoveFields::update('burrito', Parameters::fieldNames(':name', ['one', 'two', 'ten']), 'a = b'), - 'UPDATE statement not correct'); - } - - #[TestDox('update() fails when mode not set')] - public function testUpdateFailsWhenModeNotSet(): void - { - $this->expectException(DocumentException::class); - RemoveFields::update('wow', [], ''); - } - - #[TestDox('byId() succeeds for PostgreSQL')] - public function testByIdSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals("UPDATE churro SET data = data - :bite::text[] WHERE data->>'id' = :id", - RemoveFields::byId('churro', Parameters::fieldNames(':bite', ['byte'])), 'UPDATE statement not correct'); - } - - #[TestDox('byId() succeeds for SQLite')] - public function testByIdSucceedsForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals("UPDATE quesadilla SET data = json_remove(data, :bite0) WHERE data->>'id' = :id", - RemoveFields::byId('quesadilla', Parameters::fieldNames(':bite', ['byte'])), - 'UPDATE statement not correct'); - } - - #[TestDox('byId() fails when mode not set')] - public function testByIdFailsWhenModeNotSet(): void - { - $this->expectException(DocumentException::class); - RemoveFields::byId('oof', []); - } - - #[TestDox('byFields() succeeds for PostgreSQL')] - public function testByFieldsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals("UPDATE enchilada SET data = data - :sauce::text[] WHERE data->>'cheese' = :queso", - RemoveFields::byFields('enchilada', [Field::equal('cheese', 'jack', ':queso')], - Parameters::fieldNames(':sauce', ['white'])), - 'UPDATE statement not correct'); - } - - #[TestDox('byFields() succeeds for SQLite')] - public function testByFieldsSucceedsForSQLite(): void - { - Configuration::overrideMode(Mode::SQLite); - $this->assertEquals( - "UPDATE chimichanga SET data = json_remove(data, :filling0) WHERE data->>'side' = :rice", - RemoveFields::byFields('chimichanga', [Field::equal('side', 'beans', ':rice')], - Parameters::fieldNames(':filling', ['beef'])), - 'UPDATE statement not correct'); - } - - #[TestDox('byFields() fails when mode not set')] - public function testByFieldsFailsWhenModeNotSet(): void - { - $this->expectException(DocumentException::class); - RemoveFields::byFields('boing', [], []); - } - - #[TestDox('byContains() succeeds for PostgreSQL')] - public function testByContainsSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals('UPDATE food SET data = data - :drink::text[] WHERE data @> :criteria', - RemoveFields::byContains('food', Parameters::fieldNames(':drink', ['a', 'b'])), - 'UPDATE statement not correct'); - } - - #[TestDox('byContains() fails for non PostgreSQL')] - public function testByContainsFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - RemoveFields::byContains('', []); - } - - #[TestDox('byJsonPath() succeeds for PostgreSQL')] - public function testByJsonPathSucceedsForPostgreSQL(): void - { - Configuration::overrideMode(Mode::PgSQL); - $this->assertEquals( - 'UPDATE dessert SET data = data - :cake::text[] WHERE jsonb_path_exists(data, :path::jsonpath)', - RemoveFields::byJsonPath('dessert', Parameters::fieldNames(':cake', ['b', 'c'])), - 'UPDATE statement not correct'); - } - - #[TestDox('byJsonPath() fails for non PostgreSQL')] - public function testByJsonPathFailsForNonPostgreSQL(): void - { - $this->expectException(DocumentException::class); - RemoveFields::byJsonPath('', []); - } -}