Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 85b461e441 | |||
| d896e9a6c6 | |||
| 486028bd40 |
@@ -4,10 +4,14 @@ This library allows SQLite and PostgreSQL to be treated as document databases. I
|
|||||||
|
|
||||||
## Add via Composer
|
## Add via Composer
|
||||||
|
|
||||||
[](https://packagist.org/packages/bit-badger/pdo-document)
|
[
|
||||||
|
](https://packagist.org/packages/bit-badger/pdo-document#v1.0.0-rc1) [
|
||||||
|
](https://packagist.org/packages/bit-badger/pdo-document)
|
||||||
|
|
||||||
`composer require bit-badger/pdo-document`
|
`composer require bit-badger/pdo-document`
|
||||||
|
|
||||||
|
For the v1 series, the `DocumentList` type's members `hasItems` and `items` are functions; in the v2 series, they are properties. Additionally, the `Option` and `Result` types included in the project have a similar difference; see the [v1 README](https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp/src/branch/v1/README.md) for PHP 8.2 or 8.3 and the [v2 README](https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp/src/branch/main/README.md) for PHP 8.4. Both versions are supported; the v1 / v2 distinction helps composer make the right choice based on the target PHP version of your project.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### Connection Details
|
### Connection Details
|
||||||
@@ -29,4 +33,4 @@ In all generated scenarios, if the ID value is not 0 or blank, that ID will be u
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Full documentation [is available on the project site](https://relationaldocs.bitbadger.solutions/php/).
|
Full documentation [is available on the project site](https://bitbadger.solutions/open-source/pdo-document/).
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
"docs": "https://bitbadger.solutions/open-source/pdo-document/"
|
"docs": "https://bitbadger.solutions/open-source/pdo-document/"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "8.2 - 8.3",
|
"php": ">=8.4",
|
||||||
"bit-badger/inspired-by-fsharp": "^1",
|
"bit-badger/inspired-by-fsharp": "^2",
|
||||||
"netresearch/jsonmapper": "^4",
|
"netresearch/jsonmapper": "^4",
|
||||||
"ext-pdo": "*"
|
"ext-pdo": "*"
|
||||||
},
|
},
|
||||||
|
|||||||
544
composer.lock
generated
544
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ declare(strict_types=1);
|
|||||||
namespace BitBadger\PDODocument;
|
namespace BitBadger\PDODocument;
|
||||||
|
|
||||||
use BitBadger\InspiredByFSharp\Option;
|
use BitBadger\InspiredByFSharp\Option;
|
||||||
use BitBadger\PDODocument\Mapper\{Mapper, StringMapper};
|
use BitBadger\PDODocument\Mapper\Mapper;
|
||||||
use PDO;
|
use PDO;
|
||||||
use PDOException;
|
use PDOException;
|
||||||
use PDOStatement;
|
use PDOStatement;
|
||||||
@@ -89,42 +89,7 @@ class Custom
|
|||||||
*/
|
*/
|
||||||
public static function array(string $query, array $parameters, Mapper $mapper): array
|
public static function array(string $query, array $parameters, Mapper $mapper): array
|
||||||
{
|
{
|
||||||
return iterator_to_array(self::list($query, $parameters, $mapper)->items());
|
return iterator_to_array(self::list($query, $parameters, $mapper)->items);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a query that returns a JSON string of results
|
|
||||||
*
|
|
||||||
* @param string $query The query to be executed
|
|
||||||
* @param array<string, mixed> $parameters Parameters to use in executing the query
|
|
||||||
* @return string A JSON array with the results (empty results will be `[]`)
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function jsonArray(string $query, array $parameters): string
|
|
||||||
{
|
|
||||||
return '[' . implode(',', self::array($query, $parameters, new StringMapper('data'))) . ']';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a query, echoing the results to the output
|
|
||||||
*
|
|
||||||
* @param string $query The query to be executed
|
|
||||||
* @param array<string, mixed> $parameters Parameters to use in executing the query
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function outputJsonArray(string $query, array $parameters): void
|
|
||||||
{
|
|
||||||
$isFirst = true;
|
|
||||||
echo '[';
|
|
||||||
foreach (self::list($query, $parameters, new StringMapper('data'))->items() as $doc) {
|
|
||||||
if ($isFirst) {
|
|
||||||
$isFirst = false;
|
|
||||||
} else {
|
|
||||||
echo ',';
|
|
||||||
}
|
|
||||||
echo $doc;
|
|
||||||
}
|
|
||||||
echo ']';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,19 +112,6 @@ class Custom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a query that returns one or no JSON results
|
|
||||||
*
|
|
||||||
* @param string $query The query to be executed (will have "LIMIT 1" appended)
|
|
||||||
* @param array<string, mixed> $parameters Parameters to use in executing the query
|
|
||||||
* @return string The JSON document (returns `{}` if no document is found)
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function jsonSingle(string $query, array $parameters): string
|
|
||||||
{
|
|
||||||
return self::single($query, $parameters, new StringMapper('data'))->getOrDefault('{}');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a query that does not return a value
|
* Execute a query that does not return a value
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -44,24 +44,17 @@ class DocumentList
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var bool True if there are items still to be retrieved from the list, false if not */
|
||||||
* Does this list have items remaining?
|
public bool $hasItems {
|
||||||
*
|
get => !is_null($this->result);
|
||||||
* @return bool True if there are items still to be retrieved from the list, false if not
|
|
||||||
*/
|
|
||||||
public function hasItems(): bool
|
|
||||||
{
|
|
||||||
return !is_null($this->result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The items from the query result
|
* @var Generator<TDoc> The items from the document list
|
||||||
*
|
|
||||||
* @return Generator<TDoc> The items from the document list
|
|
||||||
* @throws DocumentException If this is called once the generator has been consumed
|
* @throws DocumentException If this is called once the generator has been consumed
|
||||||
*/
|
*/
|
||||||
public function items(): Generator
|
public Generator $items {
|
||||||
{
|
get {
|
||||||
if (!$this->result) {
|
if (!$this->result) {
|
||||||
if ($this->isConsumed) {
|
if ($this->isConsumed) {
|
||||||
throw new DocumentException('Cannot call items() multiple times');
|
throw new DocumentException('Cannot call items() multiple times');
|
||||||
@@ -81,6 +74,7 @@ class DocumentList
|
|||||||
$this->isConsumed = true;
|
$this->isConsumed = true;
|
||||||
$this->result = null;
|
$this->result = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map items by consuming the generator
|
* Map items by consuming the generator
|
||||||
@@ -92,7 +86,7 @@ class DocumentList
|
|||||||
*/
|
*/
|
||||||
public function map(callable $map): Generator
|
public function map(callable $map): Generator
|
||||||
{
|
{
|
||||||
foreach ($this->items() as $item) {
|
foreach ($this->items as $item) {
|
||||||
yield $map($item);
|
yield $map($item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +99,7 @@ class DocumentList
|
|||||||
*/
|
*/
|
||||||
public function iter(callable $f): void
|
public function iter(callable $f): void
|
||||||
{
|
{
|
||||||
foreach ($this->items() as $item) {
|
foreach ($this->items as $item) {
|
||||||
$f($item);
|
$f($item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +116,7 @@ class DocumentList
|
|||||||
public function mapToArray(callable $keyFunc, callable $valueFunc): array
|
public function mapToArray(callable $keyFunc, callable $valueFunc): array
|
||||||
{
|
{
|
||||||
$results = [];
|
$results = [];
|
||||||
foreach ($this->items() as $item) {
|
foreach ($this->items as $item) {
|
||||||
$results[$keyFunc($item)] = $valueFunc($item);
|
$results[$keyFunc($item)] = $valueFunc($item);
|
||||||
}
|
}
|
||||||
return $results;
|
return $results;
|
||||||
|
|||||||
252
src/Json.php
252
src/Json.php
@@ -1,252 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace BitBadger\PDODocument;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Functions to retrieve and output documents as JSON
|
|
||||||
*/
|
|
||||||
class Json
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Retrieve all JSON documents in the given table
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which documents should be retrieved
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @return string A JSON array of all documents from the table
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function all(string $tableName, array $orderBy = []): string
|
|
||||||
{
|
|
||||||
return Custom::jsonArray(Query::selectFromTable($tableName) . Query::orderBy($orderBy), []);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a JSON document by its ID
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which the document should be retrieved
|
|
||||||
* @param mixed $docId The ID of the document to retrieve
|
|
||||||
* @return string The JSON document if found, `{}` otherwise
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function byId(string $tableName, mixed $docId): string
|
|
||||||
{
|
|
||||||
return Custom::jsonSingle(Query\Find::byId($tableName, $docId), Parameters::id($docId));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve JSON documents via a comparison on JSON fields
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which documents should be retrieved
|
|
||||||
* @param Field[] $fields The field comparison to match
|
|
||||||
* @param FieldMatch|null $match How to handle multiple conditions (optional; defaults to All)
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @return string A JSON array of documents matching the given field comparison
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function byFields(string $tableName, array $fields, ?FieldMatch $match = null,
|
|
||||||
array $orderBy = []): string
|
|
||||||
{
|
|
||||||
Parameters::nameFields($fields);
|
|
||||||
return Custom::jsonArray(Query\Find::byFields($tableName, $fields, $match) . Query::orderBy($orderBy),
|
|
||||||
Parameters::addFields($fields, []));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve JSON documents via a JSON containment query (`@>`; PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param mixed[]|object $criteria The criteria for the JSON containment query
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @return string A JSON array of documents matching the JSON containment query
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function byContains(string $tableName, array|object $criteria, array $orderBy = []): string
|
|
||||||
{
|
|
||||||
return Custom::jsonArray(Query\Find::byContains($tableName) . Query::orderBy($orderBy),
|
|
||||||
Parameters::json(':criteria', $criteria));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve JSON documents via a JSON Path match query (`@?`; PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param string $path The JSON Path match string
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @return string A JSON array of documents matching the JSON Path
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function byJsonPath(string $tableName, string $path, array $orderBy = []): string
|
|
||||||
{
|
|
||||||
return Custom::jsonArray(Query\Find::byJsonPath($tableName) . Query::orderBy($orderBy), [':path' => $path]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve JSON documents via a comparison on JSON fields, returning only the first result
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which the document should be retrieved
|
|
||||||
* @param Field[] $fields The field comparison to match
|
|
||||||
* @param FieldMatch|null $match How to handle multiple conditions (optional; defaults to All)
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @return string The first JSON document if any matches are found, `{}` otherwise
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function firstByFields(string $tableName, array $fields, ?FieldMatch $match = null,
|
|
||||||
array $orderBy = []): string
|
|
||||||
{
|
|
||||||
Parameters::nameFields($fields);
|
|
||||||
return Custom::jsonSingle(Query\Find::byFields($tableName, $fields, $match) . Query::orderBy($orderBy),
|
|
||||||
Parameters::addFields($fields, []));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve JSON documents via a JSON containment query (`@>`), returning only the first result (PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param mixed[]|object $criteria The criteria for the JSON containment query
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @return string The first JSON document if any matches are found, `{}` otherwise
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function firstByContains(string $tableName, array|object $criteria, array $orderBy = []): string
|
|
||||||
{
|
|
||||||
return Custom::jsonSingle(Query\Find::byContains($tableName) . Query::orderBy($orderBy),
|
|
||||||
Parameters::json(':criteria', $criteria));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve JSON documents via a JSON Path match query (`@?`), returning only the first result (PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param string $path The JSON Path match string
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @return string The first JSON document if any matches are found, `{}` otherwise
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function firstByJsonPath(string $tableName, string $path, array $orderBy = []): string
|
|
||||||
{
|
|
||||||
return Custom::jsonSingle(Query\Find::byJsonPath($tableName) . Query::orderBy($orderBy), [':path' => $path]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output all JSON documents in the given table
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which documents should be retrieved
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function outputAll(string $tableName, array $orderBy = []): void
|
|
||||||
{
|
|
||||||
Custom::outputJsonArray(Query::selectFromTable($tableName) . Query::orderBy($orderBy), []);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output a JSON document by its ID
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which the document should be retrieved
|
|
||||||
* @param mixed $docId The ID of the document to retrieve
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function outputById(string $tableName, mixed $docId): void
|
|
||||||
{
|
|
||||||
echo self::byId($tableName, $docId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output JSON documents via a comparison on JSON fields
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which documents should be retrieved
|
|
||||||
* @param Field[] $fields The field comparison to match
|
|
||||||
* @param FieldMatch|null $match How to handle multiple conditions (optional; defaults to All)
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function outputByFields(string $tableName, array $fields, ?FieldMatch $match = null,
|
|
||||||
array $orderBy = []): void
|
|
||||||
{
|
|
||||||
Parameters::nameFields($fields);
|
|
||||||
Custom::outputJsonArray(Query\Find::byFields($tableName, $fields, $match) . Query::orderBy($orderBy),
|
|
||||||
Parameters::addFields($fields, []));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output JSON documents via a JSON containment query (`@>`; PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param mixed[]|object $criteria The criteria for the JSON containment query
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function outputByContains(string $tableName, array|object $criteria, array $orderBy = []): void
|
|
||||||
{
|
|
||||||
Custom::outputJsonArray(Query\Find::byContains($tableName) . Query::orderBy($orderBy),
|
|
||||||
Parameters::json(':criteria', $criteria));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output JSON documents via a JSON Path match query (`@?`; PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param string $path The JSON Path match string
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function outputByJsonPath(string $tableName, string $path, array $orderBy = []): void
|
|
||||||
{
|
|
||||||
Custom::outputJsonArray(Query\Find::byJsonPath($tableName) . Query::orderBy($orderBy), [':path' => $path]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output JSON documents via a comparison on JSON fields, returning only the first result
|
|
||||||
*
|
|
||||||
* @param string $tableName The table from which the document should be retrieved
|
|
||||||
* @param Field[] $fields The field comparison to match
|
|
||||||
* @param FieldMatch|null $match How to handle multiple conditions (optional; defaults to All)
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @throws DocumentException If any is encountered
|
|
||||||
*/
|
|
||||||
public static function outputFirstByFields(string $tableName, array $fields, ?FieldMatch $match = null,
|
|
||||||
array $orderBy = []): void
|
|
||||||
{
|
|
||||||
echo self::firstByFields($tableName, $fields, $match, $orderBy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output JSON documents via a JSON containment query (`@>`), returning only the first result (PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param mixed[]|object $criteria The criteria for the JSON containment query
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function outputFirstByContains(string $tableName, array|object $criteria, array $orderBy = []): void
|
|
||||||
{
|
|
||||||
echo self::firstByContains($tableName, $criteria, $orderBy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output JSON documents via a JSON Path match query (`@?`), returning only the first result (PostgreSQL only)
|
|
||||||
*
|
|
||||||
* @param string $tableName The name of the table from which documents should be retrieved
|
|
||||||
* @param string $path The JSON Path match string
|
|
||||||
* @param Field[] $orderBy Fields by which the results should be ordered (optional, default no ordering)
|
|
||||||
* @throws DocumentException If the database mode is not PostgreSQL, or if an error occurs
|
|
||||||
*/
|
|
||||||
public static function outputFirstByJsonPath(string $tableName, string $path, array $orderBy = []): void
|
|
||||||
{
|
|
||||||
echo self::firstByJsonPath($tableName, $path, $orderBy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the content type of this page's output to JSON
|
|
||||||
*/
|
|
||||||
public static function setContentType(): void
|
|
||||||
{
|
|
||||||
header('Content-Type: application/json; charset=UTF-8');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
23
test_all.sh
23
test_all.sh
@@ -1,23 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export PDO_DOC_PGSQL_HOST=localhost:8301
|
|
||||||
PG_VERSIONS=('13' '14' '15' '16' 'latest')
|
|
||||||
|
|
||||||
for PG_VERSION in "${PG_VERSIONS[@]}"
|
|
||||||
do
|
|
||||||
echo Starting PostgreSQL:$PG_VERSION
|
|
||||||
docker run -d -p 8301:5432 --name pg_test -e POSTGRES_PASSWORD=postgres postgres:$PG_VERSION
|
|
||||||
sleep 4
|
|
||||||
if [ "$PG_VERSION" = "latest" ]; then
|
|
||||||
echo Testing SQLite and PostgreSQL...
|
|
||||||
./vendor/bin/pest --testdox-text $1-tests.txt tests
|
|
||||||
else
|
|
||||||
echo Testing PostgreSQL v$PG_VERSION...
|
|
||||||
./vendor/bin/pest --testdox-text $1-pg$PG_VERSION-tests.txt tests/Integration/PostgreSQL
|
|
||||||
fi
|
|
||||||
docker stop pg_test
|
|
||||||
sleep 2
|
|
||||||
docker rm pg_test
|
|
||||||
done
|
|
||||||
|
|
||||||
cd .. || exit
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Test\Integration;
|
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base test case class for document integration tests
|
|
||||||
*/
|
|
||||||
class DocumentTestCase extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Clear the output buffer
|
|
||||||
*/
|
|
||||||
public function clearBuffer(): void
|
|
||||||
{
|
|
||||||
ob_clean();
|
|
||||||
ob_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the contents of the output buffer and end buffering
|
|
||||||
*
|
|
||||||
* @return string The contents of the output buffer
|
|
||||||
*/
|
|
||||||
public function getBufferContents(): string {
|
|
||||||
$contents = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
return $contents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,12 +11,13 @@ namespace Test\Integration;
|
|||||||
|
|
||||||
use BitBadger\PDODocument\{Configuration, Custom, Delete, DocumentException, Field};
|
use BitBadger\PDODocument\{Configuration, Custom, Delete, DocumentException, Field};
|
||||||
use BitBadger\PDODocument\Mapper\ExistsMapper;
|
use BitBadger\PDODocument\Mapper\ExistsMapper;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Test\Integration\PostgreSQL\ThrowawayDb;
|
use Test\Integration\PostgreSQL\ThrowawayDb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration Test Class wrapper for PostgreSQL integration tests
|
* Integration Test Class wrapper for PostgreSQL integration tests
|
||||||
*/
|
*/
|
||||||
class PgIntegrationTest extends DocumentTestCase
|
class PgIntegrationTest extends TestCase
|
||||||
{
|
{
|
||||||
/** @var string Database name for throwaway database */
|
/** @var string Database name for throwaway database */
|
||||||
static private string $dbName = '';
|
static private string $dbName = '';
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ describe('::list()', function () {
|
|||||||
$list = Custom::list(Query::selectFromTable(ThrowawayDb::TABLE), [], new DocumentMapper(TestDocument::class));
|
$list = Custom::list(Query::selectFromTable(ThrowawayDb::TABLE), [], new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull();
|
expect($list)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($list->items() as $ignored) $count++;
|
foreach ($list->items as $ignored) $count++;
|
||||||
expect($count)->toBe(5);
|
expect($count)->toBe(5);
|
||||||
});
|
});
|
||||||
test('returns empty list when no data found', function () {
|
test('returns empty list when no data found', function () {
|
||||||
@@ -46,7 +46,7 @@ describe('::list()', function () {
|
|||||||
Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric > :value",
|
Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric > :value",
|
||||||
[':value' => 100], new DocumentMapper(TestDocument::class)))
|
[':value' => 100], new DocumentMapper(TestDocument::class)))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -65,54 +65,16 @@ describe('::array()', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('::jsonArray()', function () {
|
|
||||||
test('returns non-empty array when data found', function () {
|
|
||||||
expect(Custom::jsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'sub' IS NOT NULL", []))
|
|
||||||
->toContain('[{', '},{', '}]');
|
|
||||||
});
|
|
||||||
test('returns empty array when no data found', function () {
|
|
||||||
expect(Custom::jsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'nothing' = '7'", []))
|
|
||||||
->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputJsonArray()', function () {
|
|
||||||
test('outputs non-empty array when data found', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Custom::outputJsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'sub' IS NOT NULL", []);
|
|
||||||
expect($this->getBufferContents())->toContain('[{', '},{', '}]');
|
|
||||||
});
|
|
||||||
test('outputs empty array when no data found', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Custom::outputJsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'nothing' = '7'", []);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::single()', function () {
|
describe('::single()', function () {
|
||||||
test('returns a document when one is found', function () {
|
test('returns a document when one is found', function () {
|
||||||
expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", [':id' => 'one'],
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", [':id' => 'one'],
|
||||||
new DocumentMapper(TestDocument::class)))
|
new DocumentMapper(TestDocument::class));
|
||||||
->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('one');
|
||||||
->get()->id->toBe('one');
|
|
||||||
});
|
});
|
||||||
test('returns no document when one is not found', function () {
|
test('returns no document when one is not found', function () {
|
||||||
expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
||||||
[':id' => 'eighty'], new DocumentMapper(TestDocument::class)))
|
[':id' => 'eighty'], new DocumentMapper(TestDocument::class)))
|
||||||
->isNone()->toBeTrue();
|
->isNone->toBeTrue();
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::jsonSingle()', function () {
|
|
||||||
test('returns a document when one is found', function () {
|
|
||||||
expect(Custom::jsonSingle('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
|
||||||
[':id' => 'one']))
|
|
||||||
->toStartWith('{"id":')->toContain('"one",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('returns no document when one is not found', function () {
|
|
||||||
expect(Custom::jsonSingle('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
|
||||||
[':id' => 'eighty']))
|
|
||||||
->toBe('{}');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ describe('::create()', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('->items()', function () {
|
describe('->items', function () {
|
||||||
test('enumerates items in the list', function () {
|
test('enumerates items in the list', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull();
|
expect($list)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($list->items() as $item) {
|
foreach ($list->items as $item) {
|
||||||
expect(['one', 'two', 'three', 'four', 'five'])->toContain($item->id);
|
expect(['one', 'two', 'three', 'four', 'five'])->toContain($item->id);
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
@@ -37,29 +37,29 @@ describe('->items()', function () {
|
|||||||
test('fails when the list is exhausted', function () {
|
test('fails when the list is exhausted', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
$ignored = iterator_to_array($list->items());
|
$ignored = iterator_to_array($list->items);
|
||||||
expect($list)->hasItems()->toBeFalse()
|
expect($list)->hasItems->toBeFalse()
|
||||||
->and(fn () => iterator_to_array($list->items()))->toThrow(DocumentException::class);
|
->and(fn () => iterator_to_array($list->items))->toThrow(DocumentException::class);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('->hasItems()', function () {
|
describe('->hasItems', function () {
|
||||||
test('returns false when no items are in the list', function () {
|
test('returns false when no items are in the list', function () {
|
||||||
expect(DocumentList::create(
|
expect(DocumentList::create(
|
||||||
Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric < 0", [],
|
Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE (data->>'num_value')::numeric < 0", [],
|
||||||
new DocumentMapper(TestDocument::class)))
|
new DocumentMapper(TestDocument::class)))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
test('returns true when items are in the list', function () {
|
test('returns true when items are in the list', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
foreach ($list->items() as $ignored) {
|
foreach ($list->items as $ignored) {
|
||||||
expect($list)->hasItems()->toBeTrue();
|
expect($list)->hasItems->toBeTrue();
|
||||||
}
|
}
|
||||||
expect($list)->hasItems()->toBeFalse();
|
expect($list)->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ describe('->map()', function () {
|
|||||||
test('transforms the list', function () {
|
test('transforms the list', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
foreach ($list->map(fn($doc) => strrev($doc->id)) as $mapped) {
|
foreach ($list->map(fn($doc) => strrev($doc->id)) as $mapped) {
|
||||||
expect(['eno', 'owt', 'eerht', 'ruof', 'evif'])->toContain($mapped);
|
expect(['eno', 'owt', 'eerht', 'ruof', 'evif'])->toContain($mapped);
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ describe('->iter()', function () {
|
|||||||
test('walks the list', function () {
|
test('walks the list', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
$splats = [];
|
$splats = [];
|
||||||
$list->iter(function ($doc) use (&$splats) { $splats[] = str_repeat('*', strlen($doc->id)); });
|
$list->iter(function ($doc) use (&$splats) { $splats[] = str_repeat('*', strlen($doc->id)); });
|
||||||
expect(implode(' ', $splats))->toBe('*** *** ***** **** ****');
|
expect(implode(' ', $splats))->toBe('*** *** ***** **** ****');
|
||||||
@@ -89,7 +89,7 @@ describe('->mapToArray()', function () {
|
|||||||
test('creates an associative array', function () {
|
test('creates an associative array', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue()
|
expect($list)->not->toBeNull()->hasItems->toBeTrue()
|
||||||
->and($list->mapToArray(fn($it) => $it->id, fn($it) => $it->value))
|
->and($list->mapToArray(fn($it) => $it->id, fn($it) => $it->value))
|
||||||
->toBe(['one' => 'FIRST!', 'two' => 'another', 'three' => '', 'four' => 'purple', 'five' => 'purple']);
|
->toBe(['one' => 'FIRST!', 'two' => 'another', 'three' => '', 'four' => 'purple', 'five' => 'purple']);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ describe('::insert()', function () {
|
|||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 'turkey', 'sub' => ['foo' => 'gobble', 'bar' => 'gobble']]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 'turkey', 'sub' => ['foo' => 'gobble', 'bar' => 'gobble']]);
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
||||||
expect($tryDoc)
|
expect($tryDoc)
|
||||||
->isSome()->toBeTrue()
|
->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())
|
->and($tryDoc->value)
|
||||||
->id->toBe('turkey')
|
->id->toBe('turkey')
|
||||||
->value->toBe('')
|
|
||||||
->num_value->toBe(0)
|
->num_value->toBe(0)
|
||||||
->sub->not->toBeNull()
|
->sub->not->toBeNull()
|
||||||
->sub->foo->toBe('gobble')
|
->sub->foo->toBe('gobble')
|
||||||
->sub->bar->toBe('gobble');
|
->sub->bar->toBe('gobble')
|
||||||
|
->and($tryDoc->value->value)->toBe('');
|
||||||
});
|
});
|
||||||
test('inserts an array with auto-number ID, not provided', function () {
|
test('inserts an array with auto-number ID, not provided', function () {
|
||||||
Configuration::$autoId = AutoId::Number;
|
Configuration::$autoId = AutoId::Number;
|
||||||
@@ -34,15 +34,15 @@ describe('::insert()', function () {
|
|||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'new', 'num_value' => 8]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'new', 'num_value' => 8]);
|
||||||
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and(json_decode($doc->get()['data']))
|
->and(json_decode($doc->value['data']))
|
||||||
->id->toBe(1);
|
->id->toBe(1);
|
||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'again', 'num_value' => 7]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'again', 'num_value' => 7]);
|
||||||
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE " . Query::whereById(docId: 2),
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE " . Query::whereById(docId: 2),
|
||||||
[':id' => 2], new ArrayMapper());
|
[':id' => 2], new ArrayMapper());
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and(json_decode($doc->get()['data']))
|
->and(json_decode($doc->value['data']))
|
||||||
->id->toBe(2);
|
->id->toBe(2);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
@@ -54,8 +54,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 7, 'value' => 'new', 'num_value' => 8]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 7, 'value' => 'new', 'num_value' => 8]);
|
||||||
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and(json_decode($doc->get()['data']))
|
->and(json_decode($doc->value['data']))
|
||||||
->id->toBe(7);
|
->id->toBe(7);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
@@ -69,8 +69,8 @@ describe('::insert()', function () {
|
|||||||
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'num_value' => 5]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'num_value' => 5]);
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 5)], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 5)], TestDocument::class);
|
||||||
expect($doc)
|
expect($doc)
|
||||||
->isSome()->toBeTrue()
|
->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->not->toBeEmpty();
|
->and($doc->value)->id->not->toBeEmpty();
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -82,8 +82,8 @@ describe('::insert()', function () {
|
|||||||
$uuid = AutoId::generateUUID();
|
$uuid = AutoId::generateUUID();
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => $uuid, 'value' => 'uuid', 'num_value' => 12]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => $uuid, 'value' => 'uuid', 'num_value' => 12]);
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 12)], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 12)], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toBe($uuid);
|
->and($doc->value)->id->toBe($uuid);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -95,8 +95,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'value' => 'new', 'num_value' => 8]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'value' => 'new', 'num_value' => 8]);
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 8)], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 8)], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toHaveLength(6);
|
->and($doc->value)->id->toHaveLength(6);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
Configuration::$idStringLength = 16;
|
Configuration::$idStringLength = 16;
|
||||||
@@ -108,8 +108,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 'my-key', 'value' => 'old', 'num_value' => 3]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 'my-key', 'value' => 'old', 'num_value' => 3]);
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toBe('my-key');
|
->and($doc->value)->id->toBe('my-key');
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -117,8 +117,8 @@ describe('::insert()', function () {
|
|||||||
test('inserts an object with no automatic ID', function () {
|
test('inserts an object with no automatic ID', function () {
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument('turkey', sub: new SubDocument('gobble', 'gobble')));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument('turkey', sub: new SubDocument('gobble', 'gobble')));
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue();
|
expect($tryDoc)->isSome->toBeTrue();
|
||||||
$doc = $tryDoc->get();
|
$doc = $tryDoc->value;
|
||||||
expect($doc)
|
expect($doc)
|
||||||
->id->toBe('turkey')
|
->id->toBe('turkey')
|
||||||
->num_value->toBe(0)
|
->num_value->toBe(0)
|
||||||
@@ -134,13 +134,13 @@ describe('::insert()', function () {
|
|||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'taco'));
|
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'taco'));
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'taco')], NumDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'taco')], NumDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toBe(1);
|
->and($doc->value)->id->toBe(1);
|
||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'burrito'));
|
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'burrito'));
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'burrito')], NumDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'burrito')], NumDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toBe(2);
|
->and($doc->value)->id->toBe(2);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -151,8 +151,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new NumDocument(64, 'large'));
|
Document::insert(ThrowawayDb::TABLE, new NumDocument(64, 'large'));
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'large')], NumDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'large')], NumDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toBe(64);
|
->and($doc->value)->id->toBe(64);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -163,8 +163,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument(value: 'something', num_value: 9));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument(value: 'something', num_value: 9));
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::exists('value')], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::exists('value')], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->not->toBeEmpty();
|
->and($doc->value)->id->not->toBeEmpty();
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -176,8 +176,8 @@ describe('::insert()', function () {
|
|||||||
$uuid = AutoId::generateUUID();
|
$uuid = AutoId::generateUUID();
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument($uuid, num_value: 14));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument($uuid, num_value: 14));
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 14)], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 14)], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toBe($uuid);
|
->and($doc->value)->id->toBe($uuid);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -189,8 +189,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument(num_value: 55));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument(num_value: 55));
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 55)], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 55)], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toHaveLength(40);
|
->and($doc->value)->id->toHaveLength(40);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
Configuration::$idStringLength = 16;
|
Configuration::$idStringLength = 16;
|
||||||
@@ -202,8 +202,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument('my-key', num_value: 3));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument('my-key', num_value: 3));
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and($doc->get())->id->toBe('my-key');
|
->and($doc->value)->id->toBe('my-key');
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -217,13 +217,13 @@ describe('::insert()', function () {
|
|||||||
describe('::save()', function () {
|
describe('::save()', function () {
|
||||||
test('inserts a new document', function () {
|
test('inserts a new document', function () {
|
||||||
Document::save(ThrowawayDb::TABLE, new TestDocument('test', sub: new SubDocument('a', 'b')));
|
Document::save(ThrowawayDb::TABLE, new TestDocument('test', sub: new SubDocument('a', 'b')));
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class))->isSome()->toBeTrue();
|
expect(Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class))->isSome->toBeTrue();
|
||||||
});
|
});
|
||||||
test('updates an existing document', function () {
|
test('updates an existing document', function () {
|
||||||
Document::save(ThrowawayDb::TABLE, new TestDocument('two', num_value: 44));
|
Document::save(ThrowawayDb::TABLE, new TestDocument('two', num_value: 44));
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue()
|
expect($tryDoc)->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())
|
->and($tryDoc->value)
|
||||||
->num_value->toBe(44)
|
->num_value->toBe(44)
|
||||||
->sub->toBeNull();
|
->sub->toBeNull();
|
||||||
});
|
});
|
||||||
@@ -233,8 +233,8 @@ describe('::update()', function () {
|
|||||||
test('replaces an existing document', function () {
|
test('replaces an existing document', function () {
|
||||||
Document::update(ThrowawayDb::TABLE, 'one', new TestDocument('one', 'howdy', 8, new SubDocument('y', 'z')));
|
Document::update(ThrowawayDb::TABLE, 'one', new TestDocument('one', 'howdy', 8, new SubDocument('y', 'z')));
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue();
|
expect($tryDoc)->isSome->toBeTrue();
|
||||||
$doc = $tryDoc->get();
|
$doc = $tryDoc->value;
|
||||||
expect($doc)
|
expect($doc)
|
||||||
->num_value->toBe(8)
|
->num_value->toBe(8)
|
||||||
->sub->not->toBeNull()
|
->sub->not->toBeNull()
|
||||||
@@ -244,6 +244,6 @@ describe('::update()', function () {
|
|||||||
});
|
});
|
||||||
test('does nothing for a non-existent document', function () {
|
test('does nothing for a non-existent document', function () {
|
||||||
Document::update(ThrowawayDb::TABLE, 'two-hundred', new TestDocument('200'));
|
Document::update(ThrowawayDb::TABLE, 'two-hundred', new TestDocument('200'));
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'two-hundred', TestDocument::class))->isNone()->toBeTrue();
|
expect(Find::byId(ThrowawayDb::TABLE, 'two-hundred', TestDocument::class))->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe('::all()', function () {
|
|||||||
$docs = Find::all(ThrowawayDb::TABLE, TestDocument::class);
|
$docs = Find::all(ThrowawayDb::TABLE, TestDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(5);
|
expect($count)->toBe(5);
|
||||||
});
|
});
|
||||||
test('sorts data ascending', function () {
|
test('sorts data ascending', function () {
|
||||||
@@ -43,25 +43,23 @@ describe('::all()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
expect(Find::all(ThrowawayDb::TABLE, TestDocument::class))
|
expect(Find::all(ThrowawayDb::TABLE, TestDocument::class))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('::byId()', function () {
|
describe('::byId()', function () {
|
||||||
test('retrieves a document via string ID', function () {
|
test('retrieves a document via string ID', function () {
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class))
|
$doc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
||||||
->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('two');
|
||||||
->get()->id->toBe('two');
|
|
||||||
});
|
});
|
||||||
test('retrieves a document via numeric ID', function () {
|
test('retrieves a document via numeric ID', function () {
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absent')]);
|
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absent')]);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 18, NumDocument::class))
|
$doc = Find::byId(ThrowawayDb::TABLE, 18, NumDocument::class);
|
||||||
->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe(18);
|
||||||
->get()->id->toBe(18);
|
|
||||||
});
|
});
|
||||||
test('returns None when a document is not found', function () {
|
test('returns None when a document is not found', function () {
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'seventy-five', TestDocument::class))->isNone()->toBeTrue();
|
expect(Find::byId(ThrowawayDb::TABLE, 'seventy-five', TestDocument::class))->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,7 +69,7 @@ describe('::byFields()', function () {
|
|||||||
TestDocument::class, FieldMatch::All);
|
TestDocument::class, FieldMatch::All);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(1);
|
expect($count)->toBe(1);
|
||||||
});
|
});
|
||||||
test('retrieves ordered matching documents', function () {
|
test('retrieves ordered matching documents', function () {
|
||||||
@@ -84,13 +82,13 @@ describe('::byFields()', function () {
|
|||||||
$docs = Find::byFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])], TestDocument::class);
|
$docs = Find::byFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])], TestDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(1);
|
expect($count)->toBe(1);
|
||||||
});
|
});
|
||||||
test('returns an empty list when no matching documents are found', function () {
|
test('returns an empty list when no matching documents are found', function () {
|
||||||
expect(Find::byFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)], TestDocument::class))
|
expect(Find::byFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)], TestDocument::class))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
test('retrieves documents matching an inArray condition', function () {
|
test('retrieves documents matching an inArray condition', function () {
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
||||||
@@ -99,7 +97,7 @@ describe('::byFields()', function () {
|
|||||||
ArrayDocument::class);
|
ArrayDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(2);
|
expect($count)->toBe(2);
|
||||||
});
|
});
|
||||||
test('returns an empty list when no documents match an inArray condition', function () {
|
test('returns an empty list when no documents match an inArray condition', function () {
|
||||||
@@ -108,7 +106,7 @@ describe('::byFields()', function () {
|
|||||||
expect(Find::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])],
|
expect(Find::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])],
|
||||||
ArrayDocument::class))
|
ArrayDocument::class))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -117,7 +115,7 @@ describe('::byContains()', function () {
|
|||||||
$docs = Find::byContains(ThrowawayDb::TABLE, ['value' => 'purple'], TestDocument::class);
|
$docs = Find::byContains(ThrowawayDb::TABLE, ['value' => 'purple'], TestDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(2);
|
expect($count)->toBe(2);
|
||||||
});
|
});
|
||||||
test('retrieves ordered matching documents', function () {
|
test('retrieves ordered matching documents', function () {
|
||||||
@@ -130,7 +128,7 @@ describe('::byContains()', function () {
|
|||||||
test('returns an empty list when no documents match', function () {
|
test('returns an empty list when no documents match', function () {
|
||||||
expect(Find::byContains(ThrowawayDb::TABLE, ['value' => 'indigo'], TestDocument::class))
|
expect(Find::byContains(ThrowawayDb::TABLE, ['value' => 'indigo'], TestDocument::class))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,7 +137,7 @@ describe('::byJsonPath()', function () {
|
|||||||
$docs = Find::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class);
|
$docs = Find::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(2);
|
expect($count)->toBe(2);
|
||||||
});
|
});
|
||||||
test('retrieves ordered matching documents', function () {
|
test('retrieves ordered matching documents', function () {
|
||||||
@@ -151,66 +149,66 @@ describe('::byJsonPath()', function () {
|
|||||||
test('returns an empty list when no documents match', function () {
|
test('returns an empty list when no documents match', function () {
|
||||||
expect(Find::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)', TestDocument::class))
|
expect(Find::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)', TestDocument::class))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('::firstByFields()', function () {
|
describe('::firstByFields()', function () {
|
||||||
test('retrieves a matching document', function () {
|
test('retrieves a matching document', function () {
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('two');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('two');
|
||||||
});
|
});
|
||||||
test('retrieves a document for multiple results', function () {
|
test('retrieves a document for multiple results', function () {
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()->and(['two', 'four'])->toContain($doc->get()->id);
|
expect($doc)->isSome->toBeTrue()->and(['two', 'four'])->toContain($doc->value->id);
|
||||||
});
|
});
|
||||||
test('retrieves a document for multiple ordered results', function () {
|
test('retrieves a document for multiple ordered results', function () {
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class,
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class,
|
||||||
orderBy: [Field::named('n:num_value DESC')]))
|
orderBy: [Field::named('n:num_value DESC')]);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('four');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('four');
|
||||||
});
|
});
|
||||||
test('returns None when no documents match', function () {
|
test('returns None when no documents match', function () {
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')], TestDocument::class))
|
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')], TestDocument::class))
|
||||||
->isNone()->toBeTrue();
|
->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('::firstByContains()', function () {
|
describe('::firstByContains()', function () {
|
||||||
test('retrieves a matching document', function () {
|
test('retrieves a matching document', function () {
|
||||||
expect(Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'FIRST!'], TestDocument::class))
|
$doc = Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'FIRST!'], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('one');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('one');
|
||||||
});
|
});
|
||||||
test('retrieves a document for multiple results', function () {
|
test('retrieves a document for multiple results', function () {
|
||||||
$doc = Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'purple'], TestDocument::class);
|
$doc = Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'purple'], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()->and(['four', 'five'])->toContain($doc->get()->id);
|
expect($doc)->isSome->toBeTrue()->and(['four', 'five'])->toContain($doc->value->id);
|
||||||
});
|
});
|
||||||
test('retrieves a document for multiple ordered results', function () {
|
test('retrieves a document for multiple ordered results', function () {
|
||||||
expect(Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'purple'], TestDocument::class,
|
$doc = Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'purple'], TestDocument::class,
|
||||||
[Field::named('sub.bar NULLS FIRST')]))
|
[Field::named('sub.bar NULLS FIRST')]);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('five');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('five');
|
||||||
});
|
});
|
||||||
test('returns None when no documents match', function () {
|
test('returns None when no documents match', function () {
|
||||||
expect(Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'indigo'], TestDocument::class))
|
expect(Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'indigo'], TestDocument::class))
|
||||||
->isNone()->toBeTrue();
|
->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('::firstByJsonPath()', function () {
|
describe('::firstByJsonPath()', function () {
|
||||||
test('retrieves a matching document', function () {
|
test('retrieves a matching document', function () {
|
||||||
expect(Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ == 10)', TestDocument::class))
|
$doc = Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ == 10)', TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('two');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('two');
|
||||||
});
|
});
|
||||||
test('retrieves a document for multiple results', function () {
|
test('retrieves a document for multiple results', function () {
|
||||||
$doc = Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class);
|
$doc = Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()->and(['four', 'five'])->toContain($doc->get()->id);
|
expect($doc)->isSome->toBeTrue()->and(['four', 'five'])->toContain($doc->value->id);
|
||||||
});
|
});
|
||||||
test('retrieves a document for multiple ordered results', function () {
|
test('retrieves a document for multiple ordered results', function () {
|
||||||
expect(Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class,
|
$doc = Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class,
|
||||||
[Field::named('id DESC')]))
|
[Field::named('id DESC')]);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('four');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('four');
|
||||||
});
|
});
|
||||||
test('returns None when no documents match', function () {
|
test('returns None when no documents match', function () {
|
||||||
expect(Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)', TestDocument::class))
|
expect(Find::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)', TestDocument::class))
|
||||||
->isNone()->toBeTrue();
|
->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,410 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
use BitBadger\PDODocument\{Custom, Delete, Document, Field, FieldMatch, Json};
|
|
||||||
use Test\Integration\ArrayDocument;
|
|
||||||
use Test\Integration\PostgreSQL\ThrowawayDb;
|
|
||||||
|
|
||||||
pest()->group('integration', 'postgresql');
|
|
||||||
|
|
||||||
// NOTE: PostgreSQL's `JSONB` type stores JSON in a binary representation which is more easily indexed and stored. One
|
|
||||||
// side effect of this is that the document returned may not have fields in the same order as the document which
|
|
||||||
// was originally stored. The ID will always be first, though, so these tests check for presence of IDs, sorting
|
|
||||||
// by IDs, etc., instead of checking the entire JSON string that should be either returned or output.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expect document ordering by verifying the index of IDs against others
|
|
||||||
*
|
|
||||||
* @param string $json The JSON string to be searched
|
|
||||||
* @param array $ids The IDs to be verified
|
|
||||||
*/
|
|
||||||
function expect_doc_order(string $json, array $ids): void
|
|
||||||
{
|
|
||||||
for ($idx = 0; $idx < sizeof($ids) - 1; $idx++) {
|
|
||||||
expect(strpos($json, '"' . $ids[$idx] . '",'))
|
|
||||||
->toBeLessThan(strpos($json, '"' . $ids[$idx + 1] . '",'),
|
|
||||||
"ID $ids[$idx] should have occurred before ID {$ids[$idx + 1]} in JSON $json");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expect to find one of several document IDs in the given JSON
|
|
||||||
* @param string $json The JSON string to be searched
|
|
||||||
* @param string ...$ids One or more IDs to be searched
|
|
||||||
*/
|
|
||||||
function expect_any(string $json, string... $ids): void
|
|
||||||
{
|
|
||||||
$exists = false;
|
|
||||||
foreach ($ids as $it) {
|
|
||||||
$exists = strpos($json, '"id": "' . $it . '",') >= 0;
|
|
||||||
if ($exists) break;
|
|
||||||
}
|
|
||||||
expect($exists)->toBeTrue('Could not find any of IDs [' . implode(', ', $ids) . "] in $json");
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('::all()', function () {
|
|
||||||
test('retrieves data', function () {
|
|
||||||
expect(Json::all(ThrowawayDb::TABLE))
|
|
||||||
->toContain('{"id": "one",', '{"id": "two",', '{"id": "three",', '{"id": "four",', '{"id": "five",');
|
|
||||||
});
|
|
||||||
test('sorts data ascending', function () {
|
|
||||||
expect_doc_order(Json::all(ThrowawayDb::TABLE, [Field::named('id')]), ['five', 'four', 'one', 'three', 'two']);
|
|
||||||
});
|
|
||||||
test('sorts data descending', function () {
|
|
||||||
expect_doc_order(Json::all(ThrowawayDb::TABLE, [Field::named('id DESC')]),
|
|
||||||
['two', 'three', 'one', 'four', 'five']);
|
|
||||||
});
|
|
||||||
test('sorts data numerically', function () {
|
|
||||||
expect_doc_order(
|
|
||||||
Json::all(ThrowawayDb::TABLE, [Field::named('sub.foo NULLS LAST'), Field::named('n:num_value')]),
|
|
||||||
['two', 'four', 'one', 'three', 'five']);
|
|
||||||
});
|
|
||||||
test('retrieves empty results', function () {
|
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
|
||||||
expect(Json::all(ThrowawayDb::TABLE))->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byId()', function () {
|
|
||||||
test('retrieves a document via string ID', function () {
|
|
||||||
expect(Json::byId(ThrowawayDb::TABLE, 'two'))->toStartWith('{"id": "two",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('retrieves a document via numeric ID', function () {
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absent')]);
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
|
||||||
expect(Json::byId(ThrowawayDb::TABLE, 18))->toStartWith('{"id": 18,')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('returns "{}" when a document is not found', function () {
|
|
||||||
expect(Json::byId(ThrowawayDb::TABLE, 'seventy-five'))->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byFields()', function () {
|
|
||||||
test('retrieves matching documents', function () {
|
|
||||||
expect(
|
|
||||||
Json::byFields(ThrowawayDb::TABLE, [Field::in('value', ['blue', 'purple']), Field::exists('sub')],
|
|
||||||
FieldMatch::All))
|
|
||||||
->toStartWith('[{"id": "four",')->toEndWith('}]');
|
|
||||||
});
|
|
||||||
test('retrieves ordered matching documents', function () {
|
|
||||||
expect_doc_order(
|
|
||||||
Json::byFields(ThrowawayDb::TABLE, [Field::equal('value', 'purple')], FieldMatch::All,
|
|
||||||
[Field::named('id')]),
|
|
||||||
['five', 'four']);
|
|
||||||
});
|
|
||||||
test('retrieves documents matching a numeric IN clause', function () {
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])]))
|
|
||||||
->toStartWith('[{"id": "three",')->toEndWith('}]');
|
|
||||||
});
|
|
||||||
test('returns an empty array when no matching documents are found', function () {
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)]))->toBe('[]');
|
|
||||||
});
|
|
||||||
test('retrieves documents matching an inArray condition', function () {
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['c'])]))
|
|
||||||
->toStartWith('[')->toContain('{"id": "first",')->toContain('{"id": "second",')->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('returns an empty array when no documents match an inArray condition', function () {
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])]))
|
|
||||||
->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byContains()', function () {
|
|
||||||
test('retrieves matching documents', function () {
|
|
||||||
expect(Json::byContains(ThrowawayDb::TABLE, ['value' => 'purple']))
|
|
||||||
->toStartWith('[')->toContain('{"id": "four",', '{"id": "five",')->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('retrieves ordered matching documents', function () {
|
|
||||||
expect_doc_order(Json::byContains(ThrowawayDb::TABLE, ['sub' => ['foo' => 'green']], [Field::named('value')]),
|
|
||||||
['two', 'four']);
|
|
||||||
});
|
|
||||||
test('returns an empty array when no documents match', function () {
|
|
||||||
expect(Json::byContains(ThrowawayDb::TABLE, ['value' => 'indigo']))->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byJsonPath()', function () {
|
|
||||||
test('retrieves matching documents', function () {
|
|
||||||
expect(Json::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)'))
|
|
||||||
->toStartWith('[')->toContain('{"id": "four",', '{"id": "five",')->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('retrieves ordered matching documents', function () {
|
|
||||||
expect_doc_order(Json::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', [Field::named('id')]),
|
|
||||||
['five', 'four']);
|
|
||||||
});
|
|
||||||
test('returns an empty array when no documents match', function () {
|
|
||||||
expect(Json::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)'))->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::firstByFields()', function () {
|
|
||||||
test('retrieves a matching document', function () {
|
|
||||||
expect(Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')]))
|
|
||||||
->toStartWith('{"id": "two",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('retrieves a document for multiple results', function () {
|
|
||||||
$doc = Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')]);
|
|
||||||
expect($doc)->toStartWith('{')->toEndWith('}');
|
|
||||||
expect_any($doc, 'two', 'four');
|
|
||||||
});
|
|
||||||
test('retrieves a document for multiple ordered results', function () {
|
|
||||||
expect(
|
|
||||||
Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')],
|
|
||||||
orderBy: [Field::named('n:num_value DESC')]))
|
|
||||||
->toStartWith('{"id": "four",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('returns "{}" when no documents match', function () {
|
|
||||||
expect(Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')]))->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::firstByContains()', function () {
|
|
||||||
test('retrieves a matching document', function () {
|
|
||||||
expect(Json::firstByContains(ThrowawayDb::TABLE, ['value' => 'FIRST!']))
|
|
||||||
->toStartWith('{"id": "one",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('retrieves a document for multiple results', function () {
|
|
||||||
$doc = Json::firstByContains(ThrowawayDb::TABLE, ['value' => 'purple']);
|
|
||||||
expect($doc)->toStartWith('{')->toEndWith('}');
|
|
||||||
expect_any($doc, 'four', 'five');
|
|
||||||
});
|
|
||||||
test('retrieves a document for multiple ordered results', function () {
|
|
||||||
expect(Json::firstByContains(ThrowawayDb::TABLE, ['value' => 'purple'], [Field::named('sub.bar NULLS FIRST')]))
|
|
||||||
->toStartWith('{"id": "five",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('returns "{}" when no documents match', function () {
|
|
||||||
expect(Json::firstByContains(ThrowawayDb::TABLE, ['value' => 'indigo']))->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::firstByJsonPath()', function () {
|
|
||||||
test('retrieves a matching document', function () {
|
|
||||||
expect(Json::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ == 10)'))
|
|
||||||
->toStartWith('{"id": "two",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('retrieves a document for multiple results', function () {
|
|
||||||
$doc = Json::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)');
|
|
||||||
expect($doc)->toStartWith('{')->toEndWith('}');
|
|
||||||
expect_any($doc, 'four', 'five');
|
|
||||||
});
|
|
||||||
test('retrieves a document for multiple ordered results', function () {
|
|
||||||
expect(Json::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', [Field::named('id DESC')]))
|
|
||||||
->toStartWith('{"id": "four",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('returns "{}" when no documents match', function () {
|
|
||||||
expect(Json::firstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)'))->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputAll()', function () {
|
|
||||||
test('outputs data', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE);
|
|
||||||
expect($this->getBufferContents())
|
|
||||||
->toContain('{"id": "one",', '{"id": "two",', '{"id": "three",', '{"id": "four",', '{"id": "five",');
|
|
||||||
});
|
|
||||||
test('sorts data ascending', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE, [Field::named('id')]);
|
|
||||||
expect_doc_order($this->getBufferContents(), ['five', 'four', 'one', 'three', 'two']);
|
|
||||||
});
|
|
||||||
test('sorts data descending', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE, [Field::named('id DESC')]);
|
|
||||||
expect_doc_order($this->getBufferContents(), ['two', 'three', 'one', 'four', 'five']);
|
|
||||||
});
|
|
||||||
test('sorts data numerically', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE, [Field::named('sub.foo NULLS LAST'), Field::named('n:num_value')]);
|
|
||||||
expect_doc_order($this->getBufferContents(), ['two', 'four', 'one', 'three', 'five']);
|
|
||||||
});
|
|
||||||
test('outputs empty results', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputById()', function () {
|
|
||||||
test('outputs a document via string ID', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputById(ThrowawayDb::TABLE, 'two');
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": "two",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs a document via numeric ID', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absent')]);
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
|
||||||
Json::outputById(ThrowawayDb::TABLE, 18);
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": 18,')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs "{}" when a document is not found', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputById(ThrowawayDb::TABLE, 'seventy-five');
|
|
||||||
expect($this->getBufferContents())->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputByFields()', function () {
|
|
||||||
test('outputs matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::in('value', ['blue', 'purple']), Field::exists('sub')],
|
|
||||||
FieldMatch::All);
|
|
||||||
expect($this->getBufferContents())->toStartWith('[{"id": "four",')->toEndWith('}]');
|
|
||||||
});
|
|
||||||
test('outputs ordered matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::equal('value', 'purple')], FieldMatch::All,
|
|
||||||
[Field::named('id')]);
|
|
||||||
expect_doc_order($this->getBufferContents(), ['five', 'four']);
|
|
||||||
});
|
|
||||||
test('outputs documents matching a numeric IN clause', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])]);
|
|
||||||
expect($this->getBufferContents())->toStartWith('[{"id": "three",')->toEndWith('}]');
|
|
||||||
});
|
|
||||||
test('outputs an empty array when no matching documents are found', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)]);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
test('outputs documents matching an inArray condition', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['c'])]);
|
|
||||||
expect($this->getBufferContents())
|
|
||||||
->toStartWith('[')->toContain('{"id": "first",', '{"id": "second",')->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('outputs an empty array when no documents match an inArray condition', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])]);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputByContains()', function () {
|
|
||||||
test('outputs matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByContains(ThrowawayDb::TABLE, ['value' => 'purple']);
|
|
||||||
expect($this->getBufferContents())
|
|
||||||
->toStartWith('[')->toContain('{"id": "four",', '{"id": "five",')->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('outputs ordered matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByContains(ThrowawayDb::TABLE, ['sub' => ['foo' => 'green']], [Field::named('value')]);
|
|
||||||
expect_doc_order($this->getBufferContents(), ['two', 'four']);
|
|
||||||
});
|
|
||||||
test('outputs an empty array when no documents match', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByContains(ThrowawayDb::TABLE, ['value' => 'indigo']);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputByJsonPath()', function () {
|
|
||||||
test('outputs matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)');
|
|
||||||
expect($this->getBufferContents())
|
|
||||||
->toStartWith('[')->toContain('{"id": "four",', '{"id": "five",')->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('outputs ordered matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', [Field::named('id')]);
|
|
||||||
expect_doc_order($this->getBufferContents(), ['five', 'four']);
|
|
||||||
});
|
|
||||||
test('outputs an empty array when no documents match', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)');
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputFirstByFields()', function () {
|
|
||||||
test('outputs a matching document', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')]);
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": "two",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs a document for multiple results', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')]);
|
|
||||||
$doc = $this->getBufferContents();
|
|
||||||
expect($doc)->toStartWith('{')->toEndWith('}');
|
|
||||||
expect_any($doc, 'two', 'four');
|
|
||||||
});
|
|
||||||
test('outputs a document for multiple ordered results', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')],
|
|
||||||
orderBy: [Field::named('n:num_value DESC')]);
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": "four",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs "{}" when no documents match', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')]);
|
|
||||||
expect($this->getBufferContents())->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputFirstByContains()', function () {
|
|
||||||
test('outputs a matching document', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByContains(ThrowawayDb::TABLE, ['value' => 'FIRST!']);
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": "one",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs a document for multiple results', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByContains(ThrowawayDb::TABLE, ['value' => 'purple']);
|
|
||||||
$doc = $this->getBufferContents();
|
|
||||||
expect($doc)->toStartWith('{')->toEndWith('}');
|
|
||||||
expect_any($doc, 'four', 'five');
|
|
||||||
});
|
|
||||||
test('outputs a document for multiple ordered results', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByContains(ThrowawayDb::TABLE, ['value' => 'purple'], [Field::named('sub.bar NULLS FIRST')]);
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": "five",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs "{}" when no documents match', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByContains(ThrowawayDb::TABLE, ['value' => 'indigo']);
|
|
||||||
expect($this->getBufferContents())->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputFirstByJsonPath()', function () {
|
|
||||||
test('outputs a matching document', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ == 10)');
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": "two",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs a document for multiple results', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)');
|
|
||||||
$doc = $this->getBufferContents();
|
|
||||||
expect($doc)->toStartWith('{')->toEndWith('}');
|
|
||||||
expect_any($doc, 'four', 'five');
|
|
||||||
});
|
|
||||||
test('outputs a document for multiple ordered results', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', [Field::named('id DESC')]);
|
|
||||||
expect($this->getBufferContents())->toStartWith('{"id": "four",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('outputs "{}" when no documents match', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 100)');
|
|
||||||
expect($this->getBufferContents())->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -15,9 +15,8 @@ pest()->group('integration', 'postgresql');
|
|||||||
describe('::byId()', function () {
|
describe('::byId()', function () {
|
||||||
test('updates an existing document', function () {
|
test('updates an existing document', function () {
|
||||||
Patch::byId(ThrowawayDb::TABLE, 'one', ['num_value' => 44]);
|
Patch::byId(ThrowawayDb::TABLE, 'one', ['num_value' => 44]);
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class))
|
$doc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class);
|
||||||
->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->num_value->toBe(44);
|
||||||
->get()->num_value->toBe(44);
|
|
||||||
});
|
});
|
||||||
test('does nothing when a document does not exist', function () {
|
test('does nothing when a document does not exist', function () {
|
||||||
$id = 'forty-seven';
|
$id = 'forty-seven';
|
||||||
@@ -42,8 +41,8 @@ describe('::byContains()', function () {
|
|||||||
test('updates existing documents', function () {
|
test('updates existing documents', function () {
|
||||||
Patch::byContains(ThrowawayDb::TABLE, ['value' => 'another'], ['num_value' => 12]);
|
Patch::byContains(ThrowawayDb::TABLE, ['value' => 'another'], ['num_value' => 12]);
|
||||||
$tryDoc = Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'another'], TestDocument::class);
|
$tryDoc = Find::firstByContains(ThrowawayDb::TABLE, ['value' => 'another'], TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue()
|
expect($tryDoc)->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())
|
->and($tryDoc->value)
|
||||||
->id->toBe('two')
|
->id->toBe('two')
|
||||||
->num_value->toBe(12);
|
->num_value->toBe(12);
|
||||||
});
|
});
|
||||||
@@ -58,8 +57,8 @@ describe('::byJsonPath()', function () {
|
|||||||
test('updates existing documents', function () {
|
test('updates existing documents', function () {
|
||||||
Patch::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', ['value' => 'blue']);
|
Patch::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', ['value' => 'blue']);
|
||||||
$docs = Find::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class);
|
$docs = Find::byJsonPath(ThrowawayDb::TABLE, '$.num_value ? (@ > 10)', TestDocument::class);
|
||||||
expect($docs)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($docs)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
foreach ($docs->items() as $item) {
|
foreach ($docs->items as $item) {
|
||||||
expect(['four', 'five'])->toContain($item->id)
|
expect(['four', 'five'])->toContain($item->id)
|
||||||
->and($item->value)->toBe('blue');
|
->and($item->value)->toBe('blue');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ describe('::byId()', function () {
|
|||||||
test('removes fields', function () {
|
test('removes fields', function () {
|
||||||
RemoveFields::byId(ThrowawayDb::TABLE, 'two', ['sub', 'value']);
|
RemoveFields::byId(ThrowawayDb::TABLE, 'two', ['sub', 'value']);
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue();
|
expect($tryDoc)->isSome->toBeTrue();
|
||||||
$doc = $tryDoc->get();
|
$doc = $tryDoc->value;
|
||||||
expect($doc)->sub->toBeNull()
|
expect($doc)->sub->toBeNull()
|
||||||
->and($doc->value)->toBeEmpty();
|
->and($doc->value)->toBeEmpty();
|
||||||
});
|
});
|
||||||
@@ -34,9 +34,8 @@ describe('::byId()', function () {
|
|||||||
describe('::byFields()', function () {
|
describe('::byFields()', function () {
|
||||||
test('removes fields from matching documents', function () {
|
test('removes fields from matching documents', function () {
|
||||||
RemoveFields::byFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], ['sub']);
|
RemoveFields::byFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], ['sub']);
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->sub->toBeNull();
|
||||||
->get()->sub->toBeNull();
|
|
||||||
});
|
});
|
||||||
test('does nothing when the field to remove does not exist', function () {
|
test('does nothing when the field to remove does not exist', function () {
|
||||||
expect(Exists::byFields(ThrowawayDb::TABLE, [Field::exists('nada')]))->toBeFalse();
|
expect(Exists::byFields(ThrowawayDb::TABLE, [Field::exists('nada')]))->toBeFalse();
|
||||||
@@ -53,8 +52,8 @@ describe('::byContains()', function () {
|
|||||||
$criteria = ['sub' => ['foo' => 'green']];
|
$criteria = ['sub' => ['foo' => 'green']];
|
||||||
RemoveFields::byContains(ThrowawayDb::TABLE, $criteria, ['value']);
|
RemoveFields::byContains(ThrowawayDb::TABLE, $criteria, ['value']);
|
||||||
$docs = Find::byContains(ThrowawayDb::TABLE, $criteria, TestDocument::class);
|
$docs = Find::byContains(ThrowawayDb::TABLE, $criteria, TestDocument::class);
|
||||||
expect($docs)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($docs)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
foreach ($docs->items() as $item) {
|
foreach ($docs->items as $item) {
|
||||||
expect(['two', 'four'])->toContain($item->id)
|
expect(['two', 'four'])->toContain($item->id)
|
||||||
->and($item->value)->toBeEmpty();
|
->and($item->value)->toBeEmpty();
|
||||||
}
|
}
|
||||||
@@ -74,8 +73,8 @@ describe('::byJsonPath()', function () {
|
|||||||
$path = '$.value ? (@ == "purple")';
|
$path = '$.value ? (@ == "purple")';
|
||||||
RemoveFields::byJsonPath(ThrowawayDb::TABLE, $path, ['sub']);
|
RemoveFields::byJsonPath(ThrowawayDb::TABLE, $path, ['sub']);
|
||||||
$docs = Find::byJsonPath(ThrowawayDb::TABLE, $path, TestDocument::class);
|
$docs = Find::byJsonPath(ThrowawayDb::TABLE, $path, TestDocument::class);
|
||||||
expect($docs)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($docs)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
foreach ($docs->items() as $item) {
|
foreach ($docs->items as $item) {
|
||||||
expect(['four', 'five'])->toContain($item->id)
|
expect(['four', 'five'])->toContain($item->id)
|
||||||
->and($item->sub)->toBeNull();
|
->and($item->sub)->toBeNull();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ describe('::list()', function () {
|
|||||||
$list = Custom::list(Query::selectFromTable(ThrowawayDb::TABLE), [], new DocumentMapper(TestDocument::class));
|
$list = Custom::list(Query::selectFromTable(ThrowawayDb::TABLE), [], new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull();
|
expect($list)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($list->items() as $ignored) $count++;
|
foreach ($list->items as $ignored) $count++;
|
||||||
expect($count)->toBe(5);
|
expect($count)->toBe(5);
|
||||||
});
|
});
|
||||||
test('returns empty list when not data is found', function () {
|
test('returns empty list when not data is found', function () {
|
||||||
expect(Custom::list(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'num_value' > :value",
|
expect(Custom::list(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'num_value' > :value",
|
||||||
[':value' => 100], new DocumentMapper(TestDocument::class)))
|
[':value' => 100], new DocumentMapper(TestDocument::class)))
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->hasItems()->toBeFalse();
|
->hasItems->toBeFalse();
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -63,53 +63,16 @@ describe('::array()', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('::jsonArray()', function () {
|
|
||||||
test('returns non-empty array when data found', function () {
|
|
||||||
expect(Custom::jsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'sub' IS NOT NULL", []))
|
|
||||||
->toContain('[{', '},{', '}]');
|
|
||||||
});
|
|
||||||
test('returns empty array when no data found', function () {
|
|
||||||
expect(Custom::jsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'nothing' = '7'", []))
|
|
||||||
->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputJsonArray()', function () {
|
|
||||||
test('outputs non-empty array when data found', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Custom::outputJsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'sub' IS NOT NULL", []);
|
|
||||||
expect($this->getBufferContents())->toContain('[{', '},{', '}]');
|
|
||||||
});
|
|
||||||
test('outputs empty array when no data found', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Custom::outputJsonArray(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'nothing' = '7'", []);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::single()', function () {
|
describe('::single()', function () {
|
||||||
test('returns a document when one is found', function () {
|
test('returns a document when one is found', function () {
|
||||||
expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", [':id' => 'one'],
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id", [':id' => 'one'],
|
||||||
new DocumentMapper(TestDocument::class)))
|
new DocumentMapper(TestDocument::class));
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('one');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('one');
|
||||||
});
|
});
|
||||||
test('returns no document when none is found', function () {
|
test('returns no document when none is found', function () {
|
||||||
expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
expect(Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
||||||
[':id' => 'eighty'], new DocumentMapper(TestDocument::class)))
|
[':id' => 'eighty'], new DocumentMapper(TestDocument::class)))
|
||||||
->isNone()->toBeTrue();
|
->isNone->toBeTrue();
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::jsonSingle()', function () {
|
|
||||||
test('returns a document when one is found', function () {
|
|
||||||
expect(Custom::jsonSingle('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
|
||||||
[':id' => 'one']))
|
|
||||||
->toStartWith('{"id":"one",')->toEndWith('}');
|
|
||||||
});
|
|
||||||
test('returns no document when one is not found', function () {
|
|
||||||
expect(Custom::jsonSingle('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = :id",
|
|
||||||
[':id' => 'eighty']))
|
|
||||||
->toBe('{}');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ describe('::create()', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('->items()', function () {
|
describe('->items', function () {
|
||||||
test('enumerates items in the list', function () {
|
test('enumerates items in the list', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull();
|
expect($list)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($list->items() as $item) {
|
foreach ($list->items as $item) {
|
||||||
expect(['one', 'two', 'three', 'four', 'five'])->toContain($item->id);
|
expect(['one', 'two', 'three', 'four', 'five'])->toContain($item->id);
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
@@ -37,27 +37,27 @@ describe('->items()', function () {
|
|||||||
test('fails when the list is exhausted', function () {
|
test('fails when the list is exhausted', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
$ignored = iterator_to_array($list->items());
|
$ignored = iterator_to_array($list->items);
|
||||||
expect($list)->hasItems()->toBeFalse()
|
expect($list)->hasItems->toBeFalse()
|
||||||
->and(fn () => iterator_to_array($list->items()))->toThrow(DocumentException::class);
|
->and(fn () => iterator_to_array($list->items))->toThrow(DocumentException::class);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('->hasItems()', function () {
|
describe('->hasItems', function () {
|
||||||
test('returns true when items exist', function () {
|
test('returns true when items exist', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
foreach ($list->items() as $ignored) {
|
foreach ($list->items as $ignored) {
|
||||||
expect($list)->hasItems()->toBeTrue();
|
expect($list)->hasItems->toBeTrue();
|
||||||
}
|
}
|
||||||
expect($list)->hasItems()->toBeFalse();
|
expect($list)->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
test('returns false when no items exist', function () {
|
test('returns false when no items exist', function () {
|
||||||
expect(DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'num_value' < 0", [],
|
expect(DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE) . " WHERE data->>'num_value' < 0", [],
|
||||||
new DocumentMapper(TestDocument::class)))
|
new DocumentMapper(TestDocument::class)))
|
||||||
->not->toBeNull()->hasItems()->toBeFalse();
|
->not->toBeNull()->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ describe('->map()', function () {
|
|||||||
test('transforms the list', function () {
|
test('transforms the list', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
foreach ($list->map(fn($doc) => strrev($doc->id)) as $mapped) {
|
foreach ($list->map(fn($doc) => strrev($doc->id)) as $mapped) {
|
||||||
expect(['eno', 'owt', 'eerht', 'ruof', 'evif'])->toContain($mapped);
|
expect(['eno', 'owt', 'eerht', 'ruof', 'evif'])->toContain($mapped);
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ describe('->iter()', function () {
|
|||||||
test('walks the list', function () {
|
test('walks the list', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue();
|
expect($list)->not->toBeNull()->hasItems->toBeTrue();
|
||||||
$splats = [];
|
$splats = [];
|
||||||
$list->iter(function ($doc) use (&$splats) { $splats[] = str_repeat('*', strlen($doc->id)); });
|
$list->iter(function ($doc) use (&$splats) { $splats[] = str_repeat('*', strlen($doc->id)); });
|
||||||
expect(implode(' ', $splats))->toBe('*** *** ***** **** ****');
|
expect(implode(' ', $splats))->toBe('*** *** ***** **** ****');
|
||||||
@@ -87,7 +87,7 @@ describe('->mapToArray()', function () {
|
|||||||
test('creates an associative array', function () {
|
test('creates an associative array', function () {
|
||||||
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
$list = DocumentList::create(Query::selectFromTable(ThrowawayDb::TABLE), [],
|
||||||
new DocumentMapper(TestDocument::class));
|
new DocumentMapper(TestDocument::class));
|
||||||
expect($list)->not->toBeNull()->hasItems()->toBeTrue()
|
expect($list)->not->toBeNull()->hasItems->toBeTrue()
|
||||||
->and($list->mapToArray(fn($it) => $it->id, fn($it) => $it->value))
|
->and($list->mapToArray(fn($it) => $it->id, fn($it) => $it->value))
|
||||||
->toBe(['one' => 'FIRST!', 'two' => 'another', 'three' => '', 'four' => 'purple', 'five' => 'purple']);
|
->toBe(['one' => 'FIRST!', 'two' => 'another', 'three' => '', 'four' => 'purple', 'five' => 'purple']);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ describe('::insert()', function () {
|
|||||||
test('inserts an array with no automatic ID', function () {
|
test('inserts an array with no automatic ID', function () {
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 'turkey', 'sub' => ['foo' => 'gobble', 'bar' => 'gobble']]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 'turkey', 'sub' => ['foo' => 'gobble', 'bar' => 'gobble']]);
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue()
|
expect($tryDoc)->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())
|
->and($tryDoc->value)
|
||||||
->id->toBe('turkey')
|
->id->toBe('turkey')
|
||||||
->num_value->toBe(0)
|
->num_value->toBe(0)
|
||||||
->sub->not->toBeNull()
|
->sub->not->toBeNull()
|
||||||
->sub->foo->toBe('gobble')
|
->sub->foo->toBe('gobble')
|
||||||
->sub->bar->toBe('gobble')
|
->sub->bar->toBe('gobble')
|
||||||
->and($tryDoc->get()->value)->toBeEmpty();
|
->and($tryDoc->value->value)->toBeEmpty();
|
||||||
});
|
});
|
||||||
test('inserts an array with auto-number ID, not provided', function () {
|
test('inserts an array with auto-number ID, not provided', function () {
|
||||||
Configuration::$autoId = AutoId::Number;
|
Configuration::$autoId = AutoId::Number;
|
||||||
@@ -33,14 +33,14 @@ describe('::insert()', function () {
|
|||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'new', 'num_value' => 8]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'new', 'num_value' => 8]);
|
||||||
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and(json_decode($doc->get()['data']))->id->toBe(1);
|
->and(json_decode($doc->value['data']))->id->toBe(1);
|
||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'again', 'num_value' => 7]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 0, 'value' => 'again', 'num_value' => 7]);
|
||||||
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = 2", [],
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE . " WHERE data->>'id' = 2", [],
|
||||||
new ArrayMapper());
|
new ArrayMapper());
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and(json_decode($doc->get()['data']))->id->toBe(2);
|
->and(json_decode($doc->value['data']))->id->toBe(2);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 7, 'value' => 'new', 'num_value' => 8]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 7, 'value' => 'new', 'num_value' => 8]);
|
||||||
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
$doc = Custom::single('SELECT data FROM ' . ThrowawayDb::TABLE, [], new ArrayMapper());
|
||||||
expect($doc)->isSome()->toBeTrue()
|
expect($doc)->isSome->toBeTrue()
|
||||||
->and(json_decode($doc->get()['data']))->id->toBe(7);
|
->and(json_decode($doc->value['data']))->id->toBe(7);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -62,8 +62,8 @@ describe('::insert()', function () {
|
|||||||
try {
|
try {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'num_value' => 5]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'num_value' => 5]);
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 5)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 5)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->not->toBeEmpty();
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->not->toBeEmpty();
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -74,8 +74,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
$uuid = AutoId::generateUUID();
|
$uuid = AutoId::generateUUID();
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => $uuid, 'value' => 'uuid', 'num_value' => 12]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => $uuid, 'value' => 'uuid', 'num_value' => 12]);
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 12)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 12)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe($uuid);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe($uuid);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -86,8 +86,8 @@ describe('::insert()', function () {
|
|||||||
try {
|
try {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'value' => 'new', 'num_value' => 8]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => '', 'value' => 'new', 'num_value' => 8]);
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 8)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 8)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toHaveLength(6);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toHaveLength(6);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
Configuration::$idStringLength = 16;
|
Configuration::$idStringLength = 16;
|
||||||
@@ -98,8 +98,8 @@ describe('::insert()', function () {
|
|||||||
try {
|
try {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 'my-key', 'value' => 'old', 'num_value' => 3]);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 'my-key', 'value' => 'old', 'num_value' => 3]);
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('my-key');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('my-key');
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -107,14 +107,14 @@ describe('::insert()', function () {
|
|||||||
test('inserts an object with no automatic ID', function () {
|
test('inserts an object with no automatic ID', function () {
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument('turkey', sub: new SubDocument('gobble', 'gobble')));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument('turkey', sub: new SubDocument('gobble', 'gobble')));
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'turkey', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue()
|
expect($tryDoc)->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())
|
->and($tryDoc->value)
|
||||||
->id->toBe('turkey')
|
->id->toBe('turkey')
|
||||||
->num_value->toBe(0)
|
->num_value->toBe(0)
|
||||||
->sub->not->toBeNull()
|
->sub->not->toBeNull()
|
||||||
->sub->foo->toBe('gobble')
|
->sub->foo->toBe('gobble')
|
||||||
->sub->bar->toBe('gobble')
|
->sub->bar->toBe('gobble')
|
||||||
->and($tryDoc->get()->value)->toBeEmpty();
|
->and($tryDoc->value->value)->toBeEmpty();
|
||||||
});
|
});
|
||||||
test('inserts an object with auto-number ID, not provided', function () {
|
test('inserts an object with auto-number ID, not provided', function () {
|
||||||
Configuration::$autoId = AutoId::Number;
|
Configuration::$autoId = AutoId::Number;
|
||||||
@@ -122,12 +122,12 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'taco'));
|
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'taco'));
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'taco')], NumDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'taco')], NumDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe(1);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe(1);
|
||||||
|
|
||||||
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'burrito'));
|
Document::insert(ThrowawayDb::TABLE, new NumDocument(value: 'burrito'));
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'burrito')], NumDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'burrito')], NumDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe(2);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe(2);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -137,8 +137,8 @@ describe('::insert()', function () {
|
|||||||
try {
|
try {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new NumDocument(64, 'large'));
|
Document::insert(ThrowawayDb::TABLE, new NumDocument(64, 'large'));
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'large')], NumDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'large')], NumDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe(64);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe(64);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -148,8 +148,8 @@ describe('::insert()', function () {
|
|||||||
try {
|
try {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument(value: 'something', num_value: 9));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument(value: 'something', num_value: 9));
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::exists('value')], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::exists('value')], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->not->toBeEmpty();
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->not->toBeEmpty();
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -160,8 +160,8 @@ describe('::insert()', function () {
|
|||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
$uuid = AutoId::generateUUID();
|
$uuid = AutoId::generateUUID();
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument($uuid, num_value: 14));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument($uuid, num_value: 14));
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 14)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 14)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe($uuid);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe($uuid);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -172,8 +172,8 @@ describe('::insert()', function () {
|
|||||||
try {
|
try {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument(num_value: 55));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument(num_value: 55));
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 55)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 55)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toHaveLength(40);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toHaveLength(40);
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
Configuration::$idStringLength = 16;
|
Configuration::$idStringLength = 16;
|
||||||
@@ -184,8 +184,8 @@ describe('::insert()', function () {
|
|||||||
try {
|
try {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
Document::insert(ThrowawayDb::TABLE, new TestDocument('my-key', num_value: 3));
|
Document::insert(ThrowawayDb::TABLE, new TestDocument('my-key', num_value: 3));
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 3)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('my-key');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('my-key');
|
||||||
} finally {
|
} finally {
|
||||||
Configuration::$autoId = AutoId::None;
|
Configuration::$autoId = AutoId::None;
|
||||||
}
|
}
|
||||||
@@ -199,13 +199,13 @@ describe('::insert()', function () {
|
|||||||
describe('::save()', function () {
|
describe('::save()', function () {
|
||||||
test('inserts a new document', function () {
|
test('inserts a new document', function () {
|
||||||
Document::save(ThrowawayDb::TABLE, new TestDocument('test', sub: new SubDocument('a', 'b')));
|
Document::save(ThrowawayDb::TABLE, new TestDocument('test', sub: new SubDocument('a', 'b')));
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class))->isSome()->toBeTrue();
|
expect(Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class))->isSome->toBeTrue();
|
||||||
});
|
});
|
||||||
test('updates an existing document', function () {
|
test('updates an existing document', function () {
|
||||||
Document::save(ThrowawayDb::TABLE, new TestDocument('two', num_value: 44));
|
Document::save(ThrowawayDb::TABLE, new TestDocument('two', num_value: 44));
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue()
|
expect($tryDoc)->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())
|
->and($tryDoc->value)
|
||||||
->num_value->toBe(44)
|
->num_value->toBe(44)
|
||||||
->sub->toBeNull();
|
->sub->toBeNull();
|
||||||
});
|
});
|
||||||
@@ -215,17 +215,17 @@ describe('::update()', function () {
|
|||||||
test('replaces an existing document', function () {
|
test('replaces an existing document', function () {
|
||||||
Document::update(ThrowawayDb::TABLE, 'one', new TestDocument('one', 'howdy', 8, new SubDocument('y', 'z')));
|
Document::update(ThrowawayDb::TABLE, 'one', new TestDocument('one', 'howdy', 8, new SubDocument('y', 'z')));
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue()
|
expect($tryDoc)->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())
|
->and($tryDoc->value)
|
||||||
->num_value->toBe(8)
|
->num_value->toBe(8)
|
||||||
->sub->not->toBeNull()
|
->sub->not->toBeNull()
|
||||||
->sub->foo->toBe('y')
|
->sub->foo->toBe('y')
|
||||||
->sub->bar->toBe('z')
|
->sub->bar->toBe('z')
|
||||||
->and($tryDoc->get()->value)->toBe('howdy');
|
->and($tryDoc->value->value)->toBe('howdy');
|
||||||
});
|
});
|
||||||
test('does nothing for a non-existent document', function () {
|
test('does nothing for a non-existent document', function () {
|
||||||
expect(Exists::byId(ThrowawayDb::TABLE, 'two-hundred'))->toBeFalse();
|
expect(Exists::byId(ThrowawayDb::TABLE, 'two-hundred'))->toBeFalse();
|
||||||
Document::update(ThrowawayDb::TABLE, 'two-hundred', new TestDocument('200'));
|
Document::update(ThrowawayDb::TABLE, 'two-hundred', new TestDocument('200'));
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'two-hundred', TestDocument::class))->isNone()->toBeTrue();
|
expect(Find::byId(ThrowawayDb::TABLE, 'two-hundred', TestDocument::class))->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe('::all()', function () {
|
|||||||
$docs = Find::all(ThrowawayDb::TABLE, TestDocument::class);
|
$docs = Find::all(ThrowawayDb::TABLE, TestDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(5);
|
expect($count)->toBe(5);
|
||||||
});
|
});
|
||||||
test('sorts data ascending', function () {
|
test('sorts data ascending', function () {
|
||||||
@@ -42,22 +42,22 @@ describe('::all()', function () {
|
|||||||
test('returns an empty list when no data exists', function () {
|
test('returns an empty list when no data exists', function () {
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
||||||
expect(Find::all(ThrowawayDb::TABLE, TestDocument::class))
|
expect(Find::all(ThrowawayDb::TABLE, TestDocument::class))
|
||||||
->not->toBeNull()->hasItems()->toBeFalse();
|
->not->toBeNull()->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('::byId()', function () {
|
describe('::byId()', function () {
|
||||||
test('returns a document when it exists', function () {
|
test('returns a document when it exists', function () {
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class))
|
$doc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('two');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('two');
|
||||||
});
|
});
|
||||||
test('returns a document with a numeric ID', function () {
|
test('returns a document with a numeric ID', function () {
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 18, TestDocument::class))
|
$doc = Find::byId(ThrowawayDb::TABLE, 18, TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('18');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('18');
|
||||||
});
|
});
|
||||||
test('returns None when no document exists', function () {
|
test('returns None when no document exists', function () {
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'seventy-five', TestDocument::class))->isNone()->toBeTrue();
|
expect(Find::byId(ThrowawayDb::TABLE, 'seventy-five', TestDocument::class))->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ describe('::byFields()', function () {
|
|||||||
TestDocument::class, FieldMatch::All);
|
TestDocument::class, FieldMatch::All);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(1);
|
expect($count)->toBe(1);
|
||||||
});
|
});
|
||||||
test('returns ordered matching documents', function () {
|
test('returns ordered matching documents', function () {
|
||||||
@@ -80,12 +80,12 @@ describe('::byFields()', function () {
|
|||||||
$docs = Find::byFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])], TestDocument::class);
|
$docs = Find::byFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])], TestDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(1);
|
expect($count)->toBe(1);
|
||||||
});
|
});
|
||||||
test('returns empty list when no documents match', function () {
|
test('returns empty list when no documents match', function () {
|
||||||
expect(Find::byFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)], TestDocument::class))
|
expect(Find::byFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)], TestDocument::class))
|
||||||
->not->toBeNull()->hasItems()->toBeFalse();
|
->not->toBeNull()->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
test('returns matching documents for inArray comparison', function () {
|
test('returns matching documents for inArray comparison', function () {
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
||||||
@@ -94,7 +94,7 @@ describe('::byFields()', function () {
|
|||||||
ArrayDocument::class);
|
ArrayDocument::class);
|
||||||
expect($docs)->not->toBeNull();
|
expect($docs)->not->toBeNull();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($docs->items() as $ignored) $count++;
|
foreach ($docs->items as $ignored) $count++;
|
||||||
expect($count)->toBe(2);
|
expect($count)->toBe(2);
|
||||||
});
|
});
|
||||||
test('returns empty list when no documents match inArray comparison', function () {
|
test('returns empty list when no documents match inArray comparison', function () {
|
||||||
@@ -102,7 +102,7 @@ describe('::byFields()', function () {
|
|||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
||||||
expect(Find::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])],
|
expect(Find::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])],
|
||||||
ArrayDocument::class))
|
ArrayDocument::class))
|
||||||
->not->toBeNull()->hasItems()->toBeFalse();
|
->not->toBeNull()->hasItems->toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -120,21 +120,21 @@ describe('::byJsonPath()', function () {
|
|||||||
|
|
||||||
describe('::firstByFields()', function () {
|
describe('::firstByFields()', function () {
|
||||||
test('returns a matching document', function () {
|
test('returns a matching document', function () {
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('two');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('two');
|
||||||
});
|
});
|
||||||
test('returns one of several matching documents', function () {
|
test('returns one of several matching documents', function () {
|
||||||
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class);
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class);
|
||||||
expect($doc)->isSome()->toBeTrue()->and(['two', 'four'])->toContain($doc->get()->id);
|
expect($doc)->isSome->toBeTrue()->and(['two', 'four'])->toContain($doc->value->id);
|
||||||
});
|
});
|
||||||
test('returns first of ordered matching documents', function () {
|
test('returns first of ordered matching documents', function () {
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class,
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')], TestDocument::class,
|
||||||
orderBy: [Field::named('n:num_value DESC')]))
|
orderBy: [Field::named('n:num_value DESC')]);
|
||||||
->isSome()->toBeTrue()->get()->id->toBe('four');
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->id->toBe('four');
|
||||||
});
|
});
|
||||||
test('returns None when no documents match', function () {
|
test('returns None when no documents match', function () {
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')], TestDocument::class))
|
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')], TestDocument::class))
|
||||||
->isNone()->toBeTrue();
|
->isNone->toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,272 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
use BitBadger\PDODocument\{Custom, Delete, Document, DocumentException, Field, FieldMatch, Json};
|
|
||||||
use Test\Integration\ArrayDocument;
|
|
||||||
use Test\Integration\SQLite\ThrowawayDb;
|
|
||||||
|
|
||||||
pest()->group('integration', 'sqlite');
|
|
||||||
|
|
||||||
/** JSON for document ID "one" */
|
|
||||||
const ONE = '{"id":"one","value":"FIRST!","num_value":0,"sub":null}';
|
|
||||||
|
|
||||||
/** JSON for document ID "two" */
|
|
||||||
const TWO = '{"id":"two","value":"another","num_value":10,"sub":{"foo":"green","bar":"blue"}}';
|
|
||||||
|
|
||||||
/** JSON for document ID "three" */
|
|
||||||
const THREE = '{"id":"three","value":"","num_value":4,"sub":null}';
|
|
||||||
|
|
||||||
/** JSON for document ID "four" */
|
|
||||||
const FOUR = '{"id":"four","value":"purple","num_value":17,"sub":{"foo":"green","bar":"red"}}';
|
|
||||||
|
|
||||||
/** JSON for document ID "five" */
|
|
||||||
const FIVE = '{"id":"five","value":"purple","num_value":18,"sub":null}';
|
|
||||||
|
|
||||||
describe('::all()', function () {
|
|
||||||
test('retrieves data', function () {
|
|
||||||
expect(Json::all(ThrowawayDb::TABLE))->toStartWith('[')->toContain(ONE, TWO, THREE, FOUR, FIVE)->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('sorts data ascending', function () {
|
|
||||||
expect(Json::all(ThrowawayDb::TABLE, [Field::named('id')]))
|
|
||||||
->toBe('[' . implode(',', [FIVE, FOUR, ONE, THREE, TWO]) . ']');
|
|
||||||
});
|
|
||||||
test('sorts data descending', function () {
|
|
||||||
expect(Json::all(ThrowawayDb::TABLE, [Field::named('id DESC')]))
|
|
||||||
->toBe('[' . implode(',', [TWO, THREE, ONE, FOUR, FIVE]) . ']');
|
|
||||||
});
|
|
||||||
test('sorts data numerically', function () {
|
|
||||||
expect(Json::all(ThrowawayDb::TABLE, [Field::named('sub.foo NULLS LAST'), Field::named('n:num_value')]))
|
|
||||||
->toBe('[' . implode(',', [TWO, FOUR, ONE, THREE, FIVE]) . ']');
|
|
||||||
});
|
|
||||||
test('returns an empty array when no data exists', function () {
|
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
|
||||||
expect(Json::all(ThrowawayDb::TABLE))->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byId()', function () {
|
|
||||||
test('returns a document when it exists', function () {
|
|
||||||
expect(Json::byId(ThrowawayDb::TABLE, 'two'))->toBe(TWO);
|
|
||||||
});
|
|
||||||
test('returns a document with a numeric ID', function () {
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
|
||||||
expect(Json::byId(ThrowawayDb::TABLE, 18))->toBe('{"id":18,"value":"howdy"}');
|
|
||||||
});
|
|
||||||
test('returns "{}" when no document exists', function () {
|
|
||||||
expect(Json::byId(ThrowawayDb::TABLE, 'seventy-five'))->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byFields()', function () {
|
|
||||||
test('returns matching documents', function () {
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::in('value', ['blue', 'purple']), Field::exists('sub')],
|
|
||||||
FieldMatch::All))
|
|
||||||
->toBe('[' . FOUR . ']');
|
|
||||||
});
|
|
||||||
test('returns ordered matching documents', function () {
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::equal('value', 'purple')], FieldMatch::All,
|
|
||||||
[Field::named('id')]))
|
|
||||||
->toBe('[' . implode(',', [FIVE, FOUR]) . ']');
|
|
||||||
});
|
|
||||||
test('returns documents matching numeric IN clause', function () {
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])]))->toBe('[' . THREE . ']');
|
|
||||||
});
|
|
||||||
test('returns empty array when no documents match', function () {
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)]))->toBe('[]');
|
|
||||||
});
|
|
||||||
test('returns matching documents for inArray comparison', function () {
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['c'])]))
|
|
||||||
->toBe('[{"id":"first","values":["a","b","c"]},{"id":"second","values":["c","d","e"]}]');
|
|
||||||
});
|
|
||||||
test('returns empty array when no documents match inArray comparison', function () {
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
expect(Json::byFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])]))->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byContains()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::byContains('', []))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::byJsonPath()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::byJsonPath('', ''))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::firstByFields()', function () {
|
|
||||||
test('returns a matching document', function () {
|
|
||||||
expect(Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')]))->toBe(TWO);
|
|
||||||
});
|
|
||||||
test('returns one of several matching documents', function () {
|
|
||||||
$doc = Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')]);
|
|
||||||
expect($doc == TWO || $doc == FOUR)->toBeTrue("Document should have been two or four (actual $doc)");
|
|
||||||
});
|
|
||||||
test('returns first of ordered matching documents', function () {
|
|
||||||
expect(Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')],
|
|
||||||
orderBy: [Field::named('n:num_value DESC')]))
|
|
||||||
->toBe(FOUR);
|
|
||||||
});
|
|
||||||
test('returns "{}" when no documents match', function () {
|
|
||||||
expect(Json::firstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')]))->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::firstByContains()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::firstByContains('', []))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::firstByJsonPath()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::firstByJsonPath('', ''))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputAll()', function () {
|
|
||||||
test('outputs data', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE);
|
|
||||||
expect($this->getBufferContents())->toStartWith('[')->toContain(ONE, TWO, THREE, FOUR, FIVE)->toEndWith(']');
|
|
||||||
});
|
|
||||||
test('sorts data ascending', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE, [Field::named('id')]);
|
|
||||||
expect($this->getBufferContents())->toBe('[' . implode(',', [FIVE, FOUR, ONE, THREE, TWO]) . ']');
|
|
||||||
});
|
|
||||||
test('sorts data descending', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE, [Field::named('id DESC')]);
|
|
||||||
expect($this->getBufferContents())->toBe('[' . implode(',', [TWO, THREE, ONE, FOUR, FIVE]) . ']');
|
|
||||||
});
|
|
||||||
test('sorts data numerically', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE, [Field::named('sub.foo NULLS LAST'), Field::named('n:num_value')]);
|
|
||||||
expect($this->getBufferContents())->toBe('[' . implode(',', [TWO, FOUR, ONE, THREE, FIVE]) . ']');
|
|
||||||
});
|
|
||||||
test('outputs an empty array when no data exists', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Custom::nonQuery('DELETE FROM ' . ThrowawayDb::TABLE, []);
|
|
||||||
Json::outputAll(ThrowawayDb::TABLE);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputById()', function () {
|
|
||||||
test('outputs a document when it exists', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputById(ThrowawayDb::TABLE, 'two');
|
|
||||||
expect($this->getBufferContents())->toBe(TWO);
|
|
||||||
});
|
|
||||||
test('outputs a document with a numeric ID', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Document::insert(ThrowawayDb::TABLE, ['id' => 18, 'value' => 'howdy']);
|
|
||||||
Json::outputById(ThrowawayDb::TABLE, 18);
|
|
||||||
expect($this->getBufferContents())->toBe('{"id":18,"value":"howdy"}');
|
|
||||||
});
|
|
||||||
test('outputs "{}" when no document exists', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputById(ThrowawayDb::TABLE, 'seventy-five');
|
|
||||||
expect($this->getBufferContents())->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputByFields()', function () {
|
|
||||||
test('outputs matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::in('value', ['blue', 'purple']), Field::exists('sub')],
|
|
||||||
FieldMatch::All);
|
|
||||||
expect($this->getBufferContents())->toBe('[' . FOUR . ']');
|
|
||||||
});
|
|
||||||
test('outputs ordered matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::equal('value', 'purple')], FieldMatch::All,
|
|
||||||
[Field::named('id')]);
|
|
||||||
expect($this->getBufferContents())->toBe('[' . implode(',', [FIVE, FOUR]) . ']');
|
|
||||||
});
|
|
||||||
test('outputs documents matching numeric IN clause', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::in('num_value', [2, 4, 6, 8])]);
|
|
||||||
expect($this->getBufferContents())->toBe('[' . THREE . ']');
|
|
||||||
});
|
|
||||||
test('outputs empty array when no documents match', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::greater('num_value', 100)]);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
test('outputs matching documents for inArray comparison', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['c'])]);
|
|
||||||
expect($this->getBufferContents())
|
|
||||||
->toBe('[{"id":"first","values":["a","b","c"]},{"id":"second","values":["c","d","e"]}]');
|
|
||||||
});
|
|
||||||
test('outputs empty array when no documents match inArray comparison', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Delete::byFields(ThrowawayDb::TABLE, [Field::notExists('absentField')]);
|
|
||||||
foreach (ArrayDocument::testDocuments() as $doc) Document::insert(ThrowawayDb::TABLE, $doc);
|
|
||||||
Json::outputByFields(ThrowawayDb::TABLE, [Field::inArray('values', ThrowawayDb::TABLE, ['j'])]);
|
|
||||||
expect($this->getBufferContents())->toBe('[]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputByContains()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::outputByContains('', []))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputByJsonPath()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::outputByJsonPath('', ''))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputFirstByFields()', function () {
|
|
||||||
test('outputs a matching document', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'another')]);
|
|
||||||
expect($this->getBufferContents())->toBe(TWO);
|
|
||||||
});
|
|
||||||
test('outputs one of several matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')]);
|
|
||||||
$doc = $this->getBufferContents();
|
|
||||||
expect($doc == TWO || $doc == FOUR)->toBeTrue("Document should have been two or four (actual $doc)");
|
|
||||||
});
|
|
||||||
test('outputs first of ordered matching documents', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('sub.foo', 'green')],
|
|
||||||
orderBy: [Field::named('n:num_value DESC')]);
|
|
||||||
expect($this->getBufferContents())->toBe(FOUR);
|
|
||||||
});
|
|
||||||
test('outputs "{}" when no documents match', function () {
|
|
||||||
$this->clearBuffer();
|
|
||||||
Json::outputFirstByFields(ThrowawayDb::TABLE, [Field::equal('value', 'absent')]);
|
|
||||||
expect($this->getBufferContents())->toBe('{}');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputFirstByContains()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::outputFirstByContains('', []))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('::outputFirstByJsonPath()', function () {
|
|
||||||
test('throws an exception', function () {
|
|
||||||
expect(fn () => Json::outputFirstByJsonPath('', ''))->toThrow(DocumentException::class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -15,8 +15,8 @@ pest()->group('integration', 'sqlite');
|
|||||||
describe('::byId()', function () {
|
describe('::byId()', function () {
|
||||||
test('updates an existing document', function () {
|
test('updates an existing document', function () {
|
||||||
Patch::byId(ThrowawayDb::TABLE, 'one', ['num_value' => 44]);
|
Patch::byId(ThrowawayDb::TABLE, 'one', ['num_value' => 44]);
|
||||||
expect(Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class))
|
$doc = Find::byId(ThrowawayDb::TABLE, 'one', TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->num_value->toBe(44);
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->num_value->toBe(44);
|
||||||
});
|
});
|
||||||
test('does nothing when no document exists', function () {
|
test('does nothing when no document exists', function () {
|
||||||
expect(Exists::byId(ThrowawayDb::TABLE, 'forty-seven'))->toBeFalse();
|
expect(Exists::byId(ThrowawayDb::TABLE, 'forty-seven'))->toBeFalse();
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ describe('::byId()', function () {
|
|||||||
test('updates an existing document', function () {
|
test('updates an existing document', function () {
|
||||||
RemoveFields::byId(ThrowawayDb::TABLE, 'two', ['sub', 'value']);
|
RemoveFields::byId(ThrowawayDb::TABLE, 'two', ['sub', 'value']);
|
||||||
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
$tryDoc = Find::byId(ThrowawayDb::TABLE, 'two', TestDocument::class);
|
||||||
expect($tryDoc)->isSome()->toBeTrue()
|
expect($tryDoc)->isSome->toBeTrue()
|
||||||
->and($tryDoc->get())->sub->toBeNull()
|
->and($tryDoc->value)->sub->toBeNull()
|
||||||
->and($tryDoc->get()->value)->toBeEmpty();
|
->and($tryDoc->value->value)->toBeEmpty();
|
||||||
});
|
});
|
||||||
test('does nothing when the field to remove does not exist', function () {
|
test('does nothing when the field to remove does not exist', function () {
|
||||||
expect(Exists::byFields(ThrowawayDb::TABLE, [Field::exists('a_field_that_does_not_exist')]))->toBeFalse();
|
expect(Exists::byFields(ThrowawayDb::TABLE, [Field::exists('a_field_that_does_not_exist')]))->toBeFalse();
|
||||||
@@ -33,8 +33,8 @@ describe('::byId()', function () {
|
|||||||
describe('::byFields()', function () {
|
describe('::byFields()', function () {
|
||||||
test('updates matching documents', function () {
|
test('updates matching documents', function () {
|
||||||
RemoveFields::byFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], ['sub']);
|
RemoveFields::byFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], ['sub']);
|
||||||
expect(Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], TestDocument::class))
|
$doc = Find::firstByFields(ThrowawayDb::TABLE, [Field::equal('num_value', 17)], TestDocument::class);
|
||||||
->isSome()->toBeTrue()->get()->sub->toBeNull();
|
expect($doc)->isSome->toBeTrue()->and($doc->value)->sub->toBeNull();
|
||||||
});
|
});
|
||||||
test('does nothing when the field to remove does not exist', function () {
|
test('does nothing when the field to remove does not exist', function () {
|
||||||
expect(Exists::byFields(ThrowawayDb::TABLE, [Field::exists('nada')]))->toBeFalse();
|
expect(Exists::byFields(ThrowawayDb::TABLE, [Field::exists('nada')]))->toBeFalse();
|
||||||
|
|||||||
@@ -11,12 +11,13 @@ namespace Test\Integration;
|
|||||||
|
|
||||||
use BitBadger\PDODocument\{Configuration, Custom, Delete, DocumentException, Field};
|
use BitBadger\PDODocument\{Configuration, Custom, Delete, DocumentException, Field};
|
||||||
use BitBadger\PDODocument\Mapper\ExistsMapper;
|
use BitBadger\PDODocument\Mapper\ExistsMapper;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Test\Integration\SQLite\ThrowawayDb;
|
use Test\Integration\SQLite\ThrowawayDb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration Test Class wrapper for SQLite integration tests
|
* Integration Test Class wrapper for SQLite integration tests
|
||||||
*/
|
*/
|
||||||
class SQLiteIntegrationTest extends DocumentTestCase
|
class SQLiteIntegrationTest extends TestCase
|
||||||
{
|
{
|
||||||
/** @var string Database name for throwaway database */
|
/** @var string Database name for throwaway database */
|
||||||
static private string $dbName = '';
|
static private string $dbName = '';
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ pest()->group('unit');
|
|||||||
describe('->map()', function () {
|
describe('->map()', function () {
|
||||||
test('returns the given array', function () {
|
test('returns the given array', function () {
|
||||||
$result = ['one' => 2, 'three' => 4, 'eight' => 'five'];
|
$result = ['one' => 2, 'three' => 4, 'eight' => 'five'];
|
||||||
expect((new ArrayMapper())->map($result))->toBe($result);
|
expect(new ArrayMapper()->map($result))->toBe($result);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ pest()->group('unit');
|
|||||||
|
|
||||||
describe('->map()', function () {
|
describe('->map()', function () {
|
||||||
test('returns item 0 in the given array', function () {
|
test('returns item 0 in the given array', function () {
|
||||||
expect((new CountMapper())->map([5, 8, 10]))->toBe(5);
|
expect(new CountMapper()->map([5, 8, 10]))->toBe(5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ describe('Constructor', function () {
|
|||||||
|
|
||||||
describe('->map()', function () {
|
describe('->map()', function () {
|
||||||
test('deserializes valid JSON', function () {
|
test('deserializes valid JSON', function () {
|
||||||
$doc = (new DocumentMapper(DocMapTestDoc::class))
|
$doc = new DocumentMapper(DocMapTestDoc::class)
|
||||||
->map(['data' => '{"id":7,"subDoc":{"id":22,"name":"tester"}}']);
|
->map(['data' => '{"id":7,"subDoc":{"id":22,"name":"tester"}}']);
|
||||||
expect($doc)
|
expect($doc)
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
@@ -46,7 +46,7 @@ describe('->map()', function () {
|
|||||||
->name->toBe('tester');
|
->name->toBe('tester');
|
||||||
});
|
});
|
||||||
test('deserializes valid JSON [Pjson]', function () {
|
test('deserializes valid JSON [Pjson]', function () {
|
||||||
$doc = (new DocumentMapper(PjsonDocument::class))->map(['data' => '{"id":"seven","name":"bob","num_value":8}']);
|
$doc = new DocumentMapper(PjsonDocument::class)->map(['data' => '{"id":"seven","name":"bob","num_value":8}']);
|
||||||
expect($doc)
|
expect($doc)
|
||||||
->not->toBeNull()
|
->not->toBeNull()
|
||||||
->id->toEqual(new PjsonId('seven'))
|
->id->toEqual(new PjsonId('seven'))
|
||||||
@@ -55,11 +55,11 @@ describe('->map()', function () {
|
|||||||
->skipped->toBeEmpty();
|
->skipped->toBeEmpty();
|
||||||
});
|
});
|
||||||
test('throws for invalid JSON', function () {
|
test('throws for invalid JSON', function () {
|
||||||
expect(fn() => (new DocumentMapper(DocMapTestDoc::class))->map(['data' => 'this is not valid']))
|
expect(fn() => new DocumentMapper(DocMapTestDoc::class)->map(['data' => 'this is not valid']))
|
||||||
->toThrow(DocumentException::class);
|
->toThrow(DocumentException::class);
|
||||||
});
|
});
|
||||||
test('throws for invalid JSON [Pjson]', function () {
|
test('throws for invalid JSON [Pjson]', function () {
|
||||||
expect(fn() => (new DocumentMapper(PjsonDocument::class))->map(['data' => 'not even close']))
|
expect(fn() => new DocumentMapper(PjsonDocument::class)->map(['data' => 'not even close']))
|
||||||
->toThrow(DocumentException::class);
|
->toThrow(DocumentException::class);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ afterEach(function () { Configuration::overrideMode(null); });
|
|||||||
describe('->map()', function () {
|
describe('->map()', function () {
|
||||||
test('returns a boolean value from index 0 [PostgreSQL]', function () {
|
test('returns a boolean value from index 0 [PostgreSQL]', function () {
|
||||||
Configuration::overrideMode(Mode::PgSQL);
|
Configuration::overrideMode(Mode::PgSQL);
|
||||||
expect((new ExistsMapper())->map([false, 'nope']))->toBeFalse();
|
expect(new ExistsMapper()->map([false, 'nope']))->toBeFalse();
|
||||||
});
|
});
|
||||||
test('returns a number value as boolean from index 0 [SQLite]', function () {
|
test('returns a number value as boolean from index 0 [SQLite]', function () {
|
||||||
Configuration::overrideMode(Mode::SQLite);
|
Configuration::overrideMode(Mode::SQLite);
|
||||||
expect((new ExistsMapper())->map([1, 'yep']))->toBeTrue();
|
expect(new ExistsMapper()->map([1, 'yep']))->toBeTrue();
|
||||||
});
|
});
|
||||||
test('throws if mode is not set', function () {
|
test('throws if mode is not set', function () {
|
||||||
expect(fn() => (new ExistsMapper())->map(['0']))->toThrow(DocumentException::class);
|
expect(fn() => new ExistsMapper()->map(['0']))->toThrow(DocumentException::class);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user