Migrate tests to Pest
This commit is contained in:
36
tests/Unit/ConfigurationTest.php
Normal file
36
tests/Unit/ConfigurationTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\{AutoId, Configuration, DocumentException};
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('::$idField', function () {
|
||||
test('has expected default value', function () {
|
||||
expect(Configuration::$idField)->toBe('id');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::$autoId', function () {
|
||||
test('has expected default value', function () {
|
||||
expect(Configuration::$autoId)->toBe(AutoId::None);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::$idStringLength', function () {
|
||||
test('has expected default value', function () {
|
||||
expect(Configuration::$idStringLength)->toBe(16);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::dbConn()', function () {
|
||||
test('throws if DSN has not been set', function () {
|
||||
Configuration::useDSN('');
|
||||
expect(fn() => Configuration::dbConn())->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
40
tests/Unit/DocumentExceptionTest.php
Normal file
40
tests/Unit/DocumentExceptionTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\DocumentException;
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('Constructor', function () {
|
||||
test('fills code and prior exception if provided', function () {
|
||||
$priorEx = new Exception('Uh oh');
|
||||
expect(new DocumentException('Test Exception', 17, $priorEx))
|
||||
->not->toBeNull()
|
||||
->getMessage()->toBe('Test Exception')
|
||||
->getCode()->toBe(17)
|
||||
->getPrevious()->toBe($priorEx);
|
||||
});
|
||||
test('uses expected code and prior exception if not provided', function () {
|
||||
expect(new DocumentException('Oops'))
|
||||
->not->toBeNull()
|
||||
->getMessage()->toBe('Oops')
|
||||
->getCode()->toBe(0)
|
||||
->getPrevious()->toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('->__toString()', function () {
|
||||
test('excludes code if 0', function () {
|
||||
$ex = new DocumentException('Test failure');
|
||||
expect("$ex")->toBe("BitBadger\PDODocument\DocumentException: Test failure\n");
|
||||
});
|
||||
test('includes code if non-zero', function () {
|
||||
$ex = new DocumentException('Oof', -6);
|
||||
expect("$ex")->toBe("BitBadger\PDODocument\DocumentException: [-6] Oof\n");
|
||||
});
|
||||
});
|
||||
20
tests/Unit/FieldMatchTest.php
Normal file
20
tests/Unit/FieldMatchTest.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\FieldMatch;
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('->toSQL()', function () {
|
||||
test('returns AND for All', function () {
|
||||
expect(FieldMatch::All)->toSQL()->toBe('AND');
|
||||
});
|
||||
test('returns OR for Any', function () {
|
||||
expect(FieldMatch::Any)->toSQL()->toBe('OR');
|
||||
});
|
||||
});
|
||||
418
tests/Unit/FieldTest.php
Normal file
418
tests/Unit/FieldTest.php
Normal file
@@ -0,0 +1,418 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\{Configuration, Field, Mode, Op};
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('->appendParameter()', function () {
|
||||
afterEach(function () { Configuration::overrideMode(null); });
|
||||
test('appends no parameter for exists', function () {
|
||||
expect(Field::exists('exists')->appendParameter([]))->toBeEmpty();
|
||||
});
|
||||
test('appends no parameter for notExists', function () {
|
||||
expect(Field::notExists('absent')->appendParameter([]))->toBeEmpty();
|
||||
});
|
||||
test('appends two parameters for between', function () {
|
||||
expect(Field::between('exists', 5, 9, '@num')->appendParameter([]))
|
||||
->toHaveLength(2)
|
||||
->toEqual(['@nummin' => 5, '@nummax' => 9]);
|
||||
});
|
||||
test('appends a parameter for each value for in', function () {
|
||||
expect(Field::in('it', ['test', 'unit', 'great'], ':val')->appendParameter([]))
|
||||
->toHaveLength(3)
|
||||
->toEqual([':val_0' => 'test', ':val_1' => 'unit', ':val_2' => 'great']);
|
||||
});
|
||||
test('appends a parameter for each value for inArray [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]))
|
||||
->toHaveLength(3)
|
||||
->toEqual([':bit_0' => '2', ':bit_1' => '8', ':bit_2' => '64']);
|
||||
})->group('postgresql');
|
||||
test('appends a parameter for each value for inArray [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::inArray('it', 'table', [2, 8, 64], ':bit')->appendParameter([]))
|
||||
->toHaveLength(3)
|
||||
->toEqual([':bit_0' => 2, ':bit_1' => 8, ':bit_2' => 64]);
|
||||
})->group('sqlite');
|
||||
test('appends a parameter for other operators', function () {
|
||||
expect(Field::equal('the_field', 33, ':test')->appendParameter([]))
|
||||
->toHaveLength(1)
|
||||
->toEqual([':test' => 33]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('->path()', function () {
|
||||
afterEach(function () { Configuration::overrideMode(null); });
|
||||
test('returns simple SQL path [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::equal('it', 'that'))->path()->toBe("data->>'it'");
|
||||
})->group('postgresql');
|
||||
test('returns simple SQL path [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::equal('top', 'that'))->path()->toBe("data->>'top'");
|
||||
})->group('sqlite');
|
||||
test('returns nested SQL path [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::equal('parts.to.the.path', ''))->path()->toBe("data#>>'{parts,to,the,path}'");
|
||||
})->group('postgresql');
|
||||
test('returns nested SQL path [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::equal('one.two.three', ''))->path()->toBe("data->'one'->'two'->>'three'");
|
||||
})->group('sqlite');
|
||||
test('returns simple JSON path [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::equal('it', 'that'))->path(true)->toBe("data->'it'");
|
||||
})->group('postgresql');
|
||||
test('returns simple JSON path [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::equal('top', 'that'))->path(true)->toBe("data->'top'");
|
||||
})->group('sqlite');
|
||||
test('returns nested JSON path [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::equal('parts.to.the.path', ''))->path(true)->toBe("data#>'{parts,to,the,path}'");
|
||||
})->group('postgresql');
|
||||
test('returns nested JSON path [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::equal('one.two.three', ''))->path(true)->toBe("data->'one'->'two'->'three'");
|
||||
})->group('sqlite');
|
||||
});
|
||||
|
||||
describe('->toWhere()', function () {
|
||||
afterEach(function () { Configuration::overrideMode(null); });
|
||||
test('generates IS NOT NULL for exists w/o qualifier [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::exists('that_field'))->toWhere()->toBe("data->>'that_field' IS NOT NULL");
|
||||
})->group('postgresql');
|
||||
test('generates IS NOT NULL for exists w/o qualifier [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::exists('that_field'))->toWhere()->toBe("data->>'that_field' IS NOT NULL");
|
||||
})->group('sqlite');
|
||||
test('generates IS NULL for notExists w/o qualifier [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::notExists('a_field'))->toWhere()->toBe("data->>'a_field' IS NULL");
|
||||
})->group('postgresql');
|
||||
test('generates IS NULL for notExists w/o qualifier [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::notExists('a_field'))->toWhere()->toBe("data->>'a_field' IS NULL");
|
||||
})->group('sqlite');
|
||||
test('generates BETWEEN for between w/o qualifier [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::between('age', 13, 17, '@age'))->toWhere()->toBe("data->>'age' BETWEEN @agemin AND @agemax");
|
||||
})->group('sqlite');
|
||||
test('generates BETWEEN for between w/o qualifier, numeric range [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::between('age', 13, 17, '@age'))->toWhere()
|
||||
->toBe("(data->>'age')::numeric BETWEEN @agemin AND @agemax");
|
||||
})->group('postgresql');
|
||||
test('generates BETWEEN for between w/o qualifier, non-numeric range [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::between('city', 'Atlanta', 'Chicago', ':city'))->toWhere()
|
||||
->toBe("data->>'city' BETWEEN :citymin AND :citymax");
|
||||
})->group('postgresql');
|
||||
test('generates BETWEEN for between w/ qualifier [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
$field = Field::between('age', 13, 17, '@age');
|
||||
$field->qualifier = 'me';
|
||||
expect($field)->toWhere()->toBe("me.data->>'age' BETWEEN @agemin AND @agemax");
|
||||
})->group('sqlite');
|
||||
test('generates BETWEEN for between w/ qualifier, numeric range [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
$field = Field::between('age', 13, 17, '@age');
|
||||
$field->qualifier = 'me';
|
||||
expect($field)->toWhere()->toBe("(me.data->>'age')::numeric BETWEEN @agemin AND @agemax");
|
||||
})->group('postgresql');
|
||||
test('generates BETWEEN for between w/ qualifier, non-numeric range [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
$field = Field::between('city', 'Atlanta', 'Chicago', ':city');
|
||||
$field->qualifier = 'me';
|
||||
expect($field)->toWhere()->toBe("me.data->>'city' BETWEEN :citymin AND :citymax");
|
||||
})->group('postgresql');
|
||||
test('generates IN for in, non-numeric values [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::in('test', ['Atlanta', 'Chicago'], ':city'))->toWhere()
|
||||
->toBe("data->>'test' IN (:city_0, :city_1)");
|
||||
})->group('postgresql');
|
||||
test('generates IN for in, numeric values [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::in('even', [2, 4, 6], ':nbr'))->toWhere()
|
||||
->toBe("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)");
|
||||
})->group('postgresql');
|
||||
test('generates IN for in [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::in('test', ['Atlanta', 'Chicago'], ':city'))->toWhere()
|
||||
->toBe("data->>'test' IN (:city_0, :city_1)");
|
||||
})->group('sqlite');
|
||||
test('generates clause for inArray [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::inArray('even', 'tbl', [2, 4, 6, 8], ':it'))->toWhere()
|
||||
->toBe("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]");
|
||||
})->group('postgresql');
|
||||
test('generates clause for inArray [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::inArray('test', 'tbl', ['Atlanta', 'Chicago'], ':city'))->toWhere()
|
||||
->toBe("EXISTS (SELECT 1 FROM json_each(tbl.data, '\$.test') WHERE value IN (:city_0, :city_1))");
|
||||
})->group('sqlite');
|
||||
test('generates clause for other operators w/o qualifier [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Field::equal('some_field', '', ':value'))->toWhere()->toBe("data->>'some_field' = :value");
|
||||
})->group('postgresql');
|
||||
test('generates clause for other operators w/o qualifier [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Field::equal('some_field', '', ':value'))->toWhere()->toBe("data->>'some_field' = :value");
|
||||
})->group('sqlite');
|
||||
test('generates no-parameter clause w/ qualifier [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
$field = Field::exists('no_field');
|
||||
$field->qualifier = 'test';
|
||||
expect($field)->toWhere()->toBe("test.data->>'no_field' IS NOT NULL");
|
||||
})->group('postgresql');
|
||||
test('generates no-parameter clause w/ qualifier [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
$field = Field::exists('no_field');
|
||||
$field->qualifier = 'test';
|
||||
expect($field)->toWhere()->toBe("test.data->>'no_field' IS NOT NULL");
|
||||
})->group('sqlite');
|
||||
test('generates parameter clause w/ qualifier [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
$field = Field::lessOrEqual('le_field', 18, ':it');
|
||||
$field->qualifier = 'q';
|
||||
expect($field)->toWhere()->toBe("(q.data->>'le_field')::numeric <= :it");
|
||||
})->group('postgresql');
|
||||
test('generates parameter clause w/ qualifier [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
$field = Field::lessOrEqual('le_field', 18, ':it');
|
||||
$field->qualifier = 'q';
|
||||
expect($field)->toWhere()->toBe("q.data->>'le_field' <= :it");
|
||||
})->group('sqlite');
|
||||
});
|
||||
|
||||
describe('::equal()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::equal('my_test', 9);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('my_test')
|
||||
->op->toBe(Op::Equal)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBe(9);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::equal('another_test', 'turkey', ':test');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('another_test')
|
||||
->op->toBe(Op::Equal)
|
||||
->paramName->toBe(':test')
|
||||
->and($field->value)->toBe('turkey');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::greater()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::greater('your_test', 4);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('your_test')
|
||||
->op->toBe(Op::Greater)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBe(4);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::greater('more_test', 'chicken', ':value');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('more_test')
|
||||
->op->toBe(Op::Greater)
|
||||
->paramName->toBe(':value')
|
||||
->and($field->value)->toBe('chicken');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::greaterOrEqual()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::greaterOrEqual('their_test', 6);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('their_test')
|
||||
->op->toBe(Op::GreaterOrEqual)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBe(6);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::greaterOrEqual('greater_test', 'poultry', ':cluck');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('greater_test')
|
||||
->op->toBe(Op::GreaterOrEqual)
|
||||
->paramName->toBe(':cluck')
|
||||
->and($field->value)->toBe('poultry');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::less()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::less('z', 32);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('z')
|
||||
->op->toBe(Op::Less)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBe(32);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::less('additional_test', 'fowl', ':boo');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('additional_test')
|
||||
->op->toBe(Op::Less)
|
||||
->paramName->toBe(':boo')
|
||||
->and($field->value)->toBe('fowl');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::lessOrEqual()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::lessOrEqual('g', 87);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('g')
|
||||
->op->toBe(Op::LessOrEqual)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBe(87);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::lessOrEqual('lesser_test', 'hen', ':woo');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('lesser_test')
|
||||
->op->toBe(Op::LessOrEqual)
|
||||
->paramName->toBe(':woo')
|
||||
->and($field->value)->toBe('hen');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::notEqual()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::notEqual('j', 65);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('j')
|
||||
->op->toBe(Op::NotEqual)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBe(65);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::notEqual('unequal_test', 'egg', ':zoo');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('unequal_test')
|
||||
->op->toBe(Op::NotEqual)
|
||||
->paramName->toBe(':zoo')
|
||||
->and($field->value)->toBe('egg');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::between()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::between('k', 'alpha', 'zed');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('k')
|
||||
->op->toBe(Op::Between)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toEqual(['alpha', 'zed']);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::between('between_test', 18, 49, ':count');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('between_test')
|
||||
->op->toBe(Op::Between)
|
||||
->paramName->toBe(':count')
|
||||
->and($field->value)->toEqual([18, 49]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::in()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::in('test', [1, 2, 3]);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('test')
|
||||
->op->toBe(Op::In)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toEqual([1, 2, 3]);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::in('unit', ['a', 'b'], ':inParam');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('unit')
|
||||
->op->toBe(Op::In)
|
||||
->paramName->toBe(':inParam')
|
||||
->and($field->value)->toEqual(['a', 'b']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::inArray()', function () {
|
||||
test('creates Field w/o parameter', function () {
|
||||
$field = Field::inArray('test', 'tbl', [1, 2, 3]);
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('test')
|
||||
->op->toBe(Op::InArray)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toEqual(['table' => 'tbl', 'values' => [1, 2, 3]]);
|
||||
});
|
||||
test('creates Field w/ parameter', function () {
|
||||
$field = Field::inArray('unit', 'tab', ['a', 'b'], ':inAParam');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('unit')
|
||||
->op->toBe(Op::InArray)
|
||||
->paramName->toBe(':inAParam')
|
||||
->and($field->value)->toEqual(['table' => 'tab', 'values' => ['a', 'b']]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::exists()', function () {
|
||||
test('creates Field', function () {
|
||||
$field = Field::exists('be_there');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('be_there')
|
||||
->op->toBe(Op::Exists)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBeEmpty();
|
||||
});
|
||||
});
|
||||
|
||||
describe('::notExists()', function () {
|
||||
test('creates Field', function () {
|
||||
$field = Field::notExists('be_absent');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('be_absent')
|
||||
->op->toBe(Op::NotExists)
|
||||
->paramName->toBeEmpty()
|
||||
->and($field->value)->toBeEmpty();
|
||||
});
|
||||
});
|
||||
|
||||
describe('::named()', function () {
|
||||
test('creates Field', function () {
|
||||
$field = Field::named('the_field');
|
||||
expect($field)
|
||||
->not->toBeNull()
|
||||
->fieldName->toBe('the_field')
|
||||
->op->toBe(Op::Equal)
|
||||
->value->toBeEmpty()
|
||||
->and($field->value)->toBeEmpty();
|
||||
});
|
||||
});
|
||||
18
tests/Unit/Mapper/ArrayMapperTest.php
Normal file
18
tests/Unit/Mapper/ArrayMapperTest.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\Mapper\ArrayMapper;
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('->map()', function () {
|
||||
test('returns the given array', function () {
|
||||
$result = ['one' => 2, 'three' => 4, 'eight' => 'five'];
|
||||
expect(new ArrayMapper()->map($result))->toBe($result);
|
||||
});
|
||||
});
|
||||
17
tests/Unit/Mapper/CountMapperTest.php
Normal file
17
tests/Unit/Mapper/CountMapperTest.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\Mapper\CountMapper;
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('->map()', function () {
|
||||
test('returns item 0 in the given array', function () {
|
||||
expect(new CountMapper()->map([5, 8, 10]))->toBe(5);
|
||||
});
|
||||
});
|
||||
65
tests/Unit/Mapper/DocumentMapperTest.php
Normal file
65
tests/Unit/Mapper/DocumentMapperTest.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\{DocumentException, Field};
|
||||
use BitBadger\PDODocument\Mapper\DocumentMapper;
|
||||
use Test\{PjsonDocument, PjsonId};
|
||||
|
||||
// ** Test class hierarchy for serialization **
|
||||
|
||||
class DocMapSubDoc
|
||||
{
|
||||
public function __construct(public int $id = 0, public string $name = '') { }
|
||||
}
|
||||
|
||||
class DocMapTestDoc
|
||||
{
|
||||
public function __construct(public int $id = 0, public DocMapSubDoc $subDoc = new DocMapSubDoc()) { }
|
||||
}
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('Constructor', function () {
|
||||
test('uses "data" as the default field name', function () {
|
||||
expect(new DocumentMapper(Field::class))->fieldName->toBe('data');
|
||||
});
|
||||
test('uses the provided field name', function () {
|
||||
expect(new DocumentMapper(Field::class, 'json'))->fieldName->toBe('json');
|
||||
});
|
||||
});
|
||||
|
||||
describe('->map()', function () {
|
||||
test('deserializes valid JSON', function () {
|
||||
$doc = new DocumentMapper(DocMapTestDoc::class)
|
||||
->map(['data' => '{"id":7,"subDoc":{"id":22,"name":"tester"}}']);
|
||||
expect($doc)
|
||||
->not->toBeNull()
|
||||
->id->toBe(7)
|
||||
->and($doc->subDoc)
|
||||
->not->toBeNull()
|
||||
->id->toBe(22)
|
||||
->name->toBe('tester');
|
||||
});
|
||||
test('deserializes valid JSON [Pjson]', function () {
|
||||
$doc = new DocumentMapper(PjsonDocument::class)->map(['data' => '{"id":"seven","name":"bob","num_value":8}']);
|
||||
expect($doc)
|
||||
->not->toBeNull()
|
||||
->id->toEqual(new PjsonId('seven'))
|
||||
->name->toBe('bob')
|
||||
->numValue->toBe(8)
|
||||
->skipped->toBeEmpty();
|
||||
});
|
||||
test('throws for invalid JSON', function () {
|
||||
expect(fn() => new DocumentMapper(DocMapTestDoc::class)->map(['data' => 'this is not valid']))
|
||||
->toThrow(DocumentException::class);
|
||||
});
|
||||
test('throws for invalid JSON [Pjson]', function () {
|
||||
expect(fn() => new DocumentMapper(PjsonDocument::class)->map(['data' => 'not even close']))
|
||||
->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
28
tests/Unit/Mapper/ExistsMapperTest.php
Normal file
28
tests/Unit/Mapper/ExistsMapperTest.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\{Configuration, DocumentException, Mode};
|
||||
use BitBadger\PDODocument\Mapper\ExistsMapper;
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
afterEach(function () { Configuration::overrideMode(null); });
|
||||
|
||||
describe('->map()', function () {
|
||||
test('returns a boolean value from index 0 [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(new ExistsMapper()->map([false, 'nope']))->toBeFalse();
|
||||
});
|
||||
test('returns a number value as boolean from index 0 [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(new ExistsMapper()->map([1, 'yep']))->toBeTrue();
|
||||
});
|
||||
test('throws if mode is not set', function () {
|
||||
expect(fn() => new ExistsMapper()->map(['0']))->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
23
tests/Unit/Mapper/StringMapperTest.php
Normal file
23
tests/Unit/Mapper/StringMapperTest.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\Mapper\StringMapper;
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('->map()', function () {
|
||||
test('returns existing string column value', function () {
|
||||
expect(new StringMapper('test_field'))->map(['test_field' => 'test_value'])->toBe('test_value');
|
||||
});
|
||||
test('returns string value of non-string column', function () {
|
||||
expect(new StringMapper('a_number'))->map(['a_number' => 6.7])->toBe('6.7');
|
||||
});
|
||||
test('returns null for a missing column', function () {
|
||||
expect(new StringMapper('something_else'))->map([])->toBeNull();
|
||||
});
|
||||
});
|
||||
23
tests/Unit/ModeTest.php
Normal file
23
tests/Unit/ModeTest.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\{DocumentException, Mode};
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('::deriveFromDSN()', function () {
|
||||
test('derives for PostgreSQL', function () {
|
||||
expect(Mode::deriveFromDSN('pgsql:Host=localhost'))->toBe(Mode::PgSQL);
|
||||
})->group('postgresql');
|
||||
test('derives for SQLite', function () {
|
||||
expect(Mode::deriveFromDSN('sqlite:data.db'))->toBe(Mode::SQLite);
|
||||
})->group('sqlite');
|
||||
test('throws for other drivers', function () {
|
||||
expect(fn() => Mode::deriveFromDSN('mysql:Host=localhost'))->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
47
tests/Unit/OpTest.php
Normal file
47
tests/Unit/OpTest.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\Op;
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('->toSQL()', function () {
|
||||
test('returns "=" for Equal', function () {
|
||||
expect(Op::Equal)->toSQL()->toBe('=');
|
||||
});
|
||||
test('returns ">" for Greater', function () {
|
||||
expect(Op::Greater)->toSQL()->toBe('>');
|
||||
});
|
||||
test('returns ">=" for GreaterOrEqual', function () {
|
||||
expect(Op::GreaterOrEqual)->toSQL()->toBe('>=');
|
||||
});
|
||||
test('returns "<" for Less', function () {
|
||||
expect(Op::Less)->toSQL()->toBe('<');
|
||||
});
|
||||
test('returns "<=" for LessOrEqual', function () {
|
||||
expect(Op::LessOrEqual)->toSQL()->toBe('<=');
|
||||
});
|
||||
test('returns "<>" for NotEqual', function () {
|
||||
expect(Op::NotEqual)->toSQL()->toBe('<>');
|
||||
});
|
||||
test('returns "BETWEEN" for Between', function () {
|
||||
expect(Op::Between)->toSQL()->toBe('BETWEEN');
|
||||
});
|
||||
test('returns "IN" for In', function () {
|
||||
expect(Op::In)->toSQL()->toBe('IN');
|
||||
});
|
||||
test('returns "?|" (escaped) for InArray', function () {
|
||||
expect(Op::InArray)->toSQL()->toBe('??|');
|
||||
});
|
||||
test('returns "IS NOT NULL" for Exists', function () {
|
||||
expect(Op::Exists)->toSQL()->toBe('IS NOT NULL');
|
||||
});
|
||||
test('returns "IS NULL" for NotExists', function () {
|
||||
expect(Op::NotExists)->toSQL()->toBe('IS NULL');
|
||||
});
|
||||
});
|
||||
85
tests/Unit/ParametersTest.php
Normal file
85
tests/Unit/ParametersTest.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\{Configuration, DocumentException, Field, Mode, Parameters};
|
||||
use Test\{PjsonDocument, PjsonId};
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
describe('::id()', function () {
|
||||
test('creates string ID parameter', function () {
|
||||
expect(Parameters::id('key'))->toEqual([':id' => 'key']);
|
||||
});
|
||||
test('creates string from numeric ID parameter', function () {
|
||||
expect(Parameters::id(7))->toEqual([':id' => '7']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::json()', function () {
|
||||
test('serializes an array', function () {
|
||||
expect(Parameters::json(':it', ['id' => 18, 'url' => 'https://www.unittest.com']))
|
||||
->toEqual([':it' => '{"id":18,"url":"https://www.unittest.com"}']);
|
||||
});
|
||||
test('serializes an array w/ an empty array value', function () {
|
||||
expect(Parameters::json(':it', ['id' => 18, 'urls' => []]))->toEqual([':it' => '{"id":18,"urls":[]}']);
|
||||
});
|
||||
test('serializes a 1-D array w/ an empty array value', function () {
|
||||
expect(Parameters::json(':it', ['urls' => []]))->toEqual([':it' => '{"urls":[]}']);
|
||||
});
|
||||
test('serializes a stdClass instance', function () {
|
||||
$obj = new stdClass();
|
||||
$obj->id = 19;
|
||||
$obj->url = 'https://testhere.info';
|
||||
expect(Parameters::json(':it', $obj))->toEqual([':it' => '{"id":19,"url":"https://testhere.info"}']);
|
||||
});
|
||||
test('serializes a Pjson class instance', function () {
|
||||
expect(Parameters::json(':it', new PjsonDocument(new PjsonId('999'), 'a test', 98, 'nothing')))
|
||||
->toEqual([':it' => '{"id":"999","name":"a test","num_value":98}']);
|
||||
});
|
||||
test('serializes an array of Pjson class instances', function () {
|
||||
expect(Parameters::json(':it',
|
||||
['pjson' => [new PjsonDocument(new PjsonId('997'), 'another test', 94, 'nothing')]]))
|
||||
->toEqual([':it' => '{"pjson":[{"id":"997","name":"another test","num_value":94}]}']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::nameFields()', function () {
|
||||
test('provides missing parameter names', function () {
|
||||
$named = [Field::equal('it', 17), Field::equal('also', 22, ':also'), Field::equal('other', 24)];
|
||||
Parameters::nameFields($named);
|
||||
expect($named)
|
||||
->toHaveLength(3)
|
||||
->sequence(
|
||||
fn($it) => $it->paramName->toBe(':field0'),
|
||||
fn($it) => $it->paramName->toBe(':also'),
|
||||
fn($it) => $it->paramName->toBe(':field2'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('::addFields()', function () {
|
||||
test('appends to an existing parameter array', function () {
|
||||
expect(Parameters::addFields([Field::equal('b', 'two', ':b'), Field::equal('z', 18, ':z')], [':a' => 1]))
|
||||
->toEqual([':a' => 1, ':b' => 'two', ':z' => 18]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::fieldNames()', function () {
|
||||
afterEach(function () { Configuration::overrideMode(null); });
|
||||
test('generates names [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Parameters::fieldNames(':names', ['one', 'two', 'seven']))->toEqual([':names' => "{one,two,seven}"]);
|
||||
})->group('postgresql');
|
||||
test('generates names [SQLite]', function () {
|
||||
Configuration::overrideMode(Mode::SQLite);
|
||||
expect(Parameters::fieldNames(':it', ['test', 'unit', 'wow']))
|
||||
->toEqual([':it0' => '$.test', ':it1' => '$.unit', ':it2' => '$.wow']);
|
||||
})->group('sqlite');
|
||||
test('throws when mode is not set', function () {
|
||||
expect(fn() => Parameters::fieldNames('', []))->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
51
tests/Unit/Query/CountTest.php
Normal file
51
tests/Unit/Query/CountTest.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @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');
|
||||
});
|
||||
65
tests/Unit/Query/DefinitionTest.php
Normal file
65
tests/Unit/Query/DefinitionTest.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @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');
|
||||
});
|
||||
52
tests/Unit/Query/DeleteTest.php
Normal file
52
tests/Unit/Query/DeleteTest.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @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);
|
||||
});
|
||||
});
|
||||
59
tests/Unit/Query/ExistsTest.php
Normal file
59
tests/Unit/Query/ExistsTest.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @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');
|
||||
});
|
||||
53
tests/Unit/Query/FindTest.php
Normal file
53
tests/Unit/Query/FindTest.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @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');
|
||||
});
|
||||
68
tests/Unit/Query/PatchTest.php
Normal file
68
tests/Unit/Query/PatchTest.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @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');
|
||||
});
|
||||
86
tests/Unit/Query/RemoveFieldsTest.php
Normal file
86
tests/Unit/Query/RemoveFieldsTest.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @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');
|
||||
});
|
||||
201
tests/Unit/QueryTest.php
Normal file
201
tests/Unit/QueryTest.php
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\{AutoId, Configuration, DocumentException, Field, FieldMatch, Mode, Query};
|
||||
|
||||
pest()->group('unit');
|
||||
|
||||
beforeEach(function () { Configuration::overrideMode(Mode::SQLite); });
|
||||
afterEach(function () { Configuration::overrideMode(null); });
|
||||
|
||||
describe('::selectFromTable()', function () {
|
||||
test('correctly forms a query', function () {
|
||||
expect(Query::selectFromTable('testing'))->toBe('SELECT data FROM testing');
|
||||
});
|
||||
});
|
||||
|
||||
describe('::whereByFields()', function () {
|
||||
test('generates a single field correctly', function () {
|
||||
expect(Query::whereByFields([Field::lessOrEqual('test_field', '', ':it')]))->toBe("data->>'test_field' <= :it");
|
||||
});
|
||||
test('generates all fields correctly', function () {
|
||||
expect(Query::whereByFields(
|
||||
|
||||
[Field::lessOrEqual('test_field', '', ':it'), Field::equal('other_field', '', ':other')]))
|
||||
->toBe("data->>'test_field' <= :it AND data->>'other_field' = :other",);
|
||||
});
|
||||
test('generates any field correctly', function () {
|
||||
expect(Query::whereByFields(
|
||||
[Field::lessOrEqual('test_field', '', ':it'), Field::equal('other_field', '', ':other')],
|
||||
FieldMatch::Any))
|
||||
->toBe("data->>'test_field' <= :it OR data->>'other_field' = :other");
|
||||
});
|
||||
});
|
||||
|
||||
describe('::whereById()', function () {
|
||||
test('uses default parameter name', function () {
|
||||
expect(Query::whereById())->toBe("data->>'id' = :id");
|
||||
});
|
||||
test('uses provided parameter name', function () {
|
||||
expect(Query::whereById(':di'))->toBe("data->>'id' = :di");
|
||||
});
|
||||
});
|
||||
|
||||
describe('::whereDataContains()', function () {
|
||||
test('uses default parameter [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::whereDataContains())->toBe('data @> :criteria');
|
||||
});
|
||||
test('uses provided parameter [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::whereDataContains(':it'))->toBe('data @> :it');
|
||||
});
|
||||
test('throws [SQLite]', function () {
|
||||
expect(fn () => Query::whereDataContains())->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::whereJsonPathMatches()', function () {
|
||||
test('uses default parameter [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::whereJsonPathMatches())->toBe('jsonb_path_exists(data, :path::jsonpath)');
|
||||
});
|
||||
test('uses provided parameter [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::whereJsonPathMatches(':road'))->toBe('jsonb_path_exists(data, :road::jsonpath)');
|
||||
});
|
||||
test('throws [SQLite]', function () {
|
||||
expect(fn () => Query::whereJsonPathMatches())->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::insert()', function () {
|
||||
test('generates with no auto-ID [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::insert('test_tbl'))->toBe('INSERT INTO test_tbl VALUES (:data)');
|
||||
});
|
||||
test('generates with no auto-ID [SQLite]', function () {
|
||||
expect(Query::insert('test_tbl'))->toBe('INSERT INTO test_tbl VALUES (:data)');
|
||||
});
|
||||
test('generates with auto numeric ID [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::insert('test_tbl', AutoId::Number))
|
||||
->toBe("INSERT INTO test_tbl VALUES (:data::jsonb || ('{\"id\":' "
|
||||
. "|| (SELECT COALESCE(MAX((data->>'id')::numeric), 0) + 1 FROM test_tbl) || '}')::jsonb)");
|
||||
});
|
||||
test('generates with auto numeric ID [SQLite]', function () {
|
||||
expect(Query::insert('test_tbl', AutoId::Number))
|
||||
->toBe("INSERT INTO test_tbl VALUES (json_set(:data, '$.id', "
|
||||
. "(SELECT coalesce(max(data->>'id'), 0) + 1 FROM test_tbl)))");
|
||||
});
|
||||
test('generates with auto UUID [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::insert('test_tbl', AutoId::UUID))
|
||||
->toStartWith("INSERT INTO test_tbl VALUES (:data::jsonb || '{\"id\":\"")
|
||||
->toEndWith("\"}')");
|
||||
});
|
||||
test('generates with auto UUID [SQLite]', function () {
|
||||
expect(Query::insert('test_tbl', AutoId::UUID))
|
||||
->toStartWith("INSERT INTO test_tbl VALUES (json_set(:data, '$.id', '")
|
||||
->toEndWith("'))");
|
||||
});
|
||||
test('generates with auto random string [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
Configuration::$idStringLength = 8;
|
||||
try {
|
||||
$query = Query::insert('test_tbl', AutoId::RandomString);
|
||||
expect($query)
|
||||
->toStartWith("INSERT INTO test_tbl VALUES (:data::jsonb || '{\"id\":\"")
|
||||
->toEndWith("\"}')")
|
||||
->and(str_replace(["INSERT INTO test_tbl VALUES (:data::jsonb || '{\"id\":\"", "\"}')"], '', $query))
|
||||
->toHaveLength(8);
|
||||
} finally {
|
||||
Configuration::$idStringLength = 16;
|
||||
}
|
||||
});
|
||||
test('generates with auto random string [SQLite]', function () {
|
||||
$query = Query::insert('test_tbl', AutoId::RandomString);
|
||||
expect($query)
|
||||
->toStartWith("INSERT INTO test_tbl VALUES (json_set(:data, '$.id', '")
|
||||
->toEndWith("'))")
|
||||
->and(str_replace(["INSERT INTO test_tbl VALUES (json_set(:data, '$.id', '", "'))"], '', $query))
|
||||
->toHaveLength(16);
|
||||
});
|
||||
test('throws when mode not set', function () {
|
||||
Configuration::overrideMode(null);
|
||||
expect(fn () => Query::insert('kaboom'))->toThrow(DocumentException::class);
|
||||
});
|
||||
});
|
||||
|
||||
describe('::save()', function () {
|
||||
test('generates the correct query', function () {
|
||||
expect(Query::save('test_tbl'))
|
||||
->toBe("INSERT INTO test_tbl VALUES (:data) ON CONFLICT ((data->>'id')) DO UPDATE SET data = EXCLUDED.data");
|
||||
});
|
||||
});
|
||||
|
||||
describe('::update()', function () {
|
||||
test('generates the correct query', function () {
|
||||
expect(Query::update('testing'))->toBe("UPDATE testing SET data = :data WHERE data->>'id' = :id");
|
||||
});
|
||||
});
|
||||
|
||||
describe('::orderBy()', function () {
|
||||
test('returns blank for no criteria [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::orderBy([]))->toBeEmpty();
|
||||
});
|
||||
test('returns blank for no criteria [SQLite]', function () {
|
||||
expect(Query::orderBy([]))->toBeEmpty();
|
||||
});
|
||||
test('generates one field with no direction [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::orderBy([Field::named('TestField')]))->toBe(" ORDER BY data->>'TestField'");
|
||||
});
|
||||
test('generates one field with no direction [SQLite]', function () {
|
||||
expect(Query::orderBy([Field::named('TestField')]))->toBe(" ORDER BY data->>'TestField'");
|
||||
});
|
||||
test('generates with one qualified field [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
$field = Field::named('TestField');
|
||||
$field->qualifier = 'qual';
|
||||
expect(Query::orderBy([$field]))->toBe(" ORDER BY qual.data->>'TestField'");
|
||||
});
|
||||
test('generates with one qualified field [SQLite]', function () {
|
||||
$field = Field::named('TestField');
|
||||
$field->qualifier = 'qual';
|
||||
expect(Query::orderBy([$field]))->toBe(" ORDER BY qual.data->>'TestField'");
|
||||
});
|
||||
test('generates with multiple fields and direction [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::orderBy(
|
||||
[Field::named('Nested.Test.Field DESC'), Field::named('AnotherField'), Field::named('It DESC')]))
|
||||
->toBe(" ORDER BY data#>>'{Nested,Test,Field}' DESC, data->>'AnotherField', data->>'It' DESC");
|
||||
});
|
||||
test('generates with multiple fields and direction [SQLite]', function () {
|
||||
expect(Query::orderBy(
|
||||
[Field::named('Nested.Test.Field DESC'), Field::named('AnotherField'), Field::named('It DESC')]))
|
||||
->toBe(" ORDER BY data->'Nested'->'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC");
|
||||
});
|
||||
test('generates with numeric field [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::orderBy([Field::named('n:Test')]))->toBe(" ORDER BY (data->>'Test')::numeric");
|
||||
});
|
||||
test('generates with numeric field [SQLite]', function () {
|
||||
expect(Query::orderBy([Field::named('n:Test')]))->toBe(" ORDER BY data->>'Test'");
|
||||
});
|
||||
test('generates case-insensitive ordering [PostgreSQL]', function () {
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
expect(Query::orderBy([Field::named('i:Test.Field DESC NULLS FIRST')]))
|
||||
->toBe(" ORDER BY LOWER(data#>>'{Test,Field}') DESC NULLS FIRST");
|
||||
});
|
||||
test('generates case-insensitive ordering [SQLite]', function () {
|
||||
expect(Query::orderBy([Field::named('i:Test.Field ASC NULLS LAST')]))
|
||||
->toBe(" ORDER BY data->'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user