diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml
index d28186d3..c5362d69 100644
--- a/.github/workflows/psalm.yml
+++ b/.github/workflows/psalm.yml
@@ -24,4 +24,15 @@ jobs:
run: composer install --no-progress --prefer-dist
- name: Run Psalm
- run: vendor/bin/psalm --output-format=github
+ run: vendor/bin/psalm --show-info=true --output-format=github
+
+ - name: Run Psalm
+ id: psalm
+ run: |
+ # Run Psalm and use tee to print output and save it to psalm.log
+ vendor/bin/psalm --no-cache --show-info=true --output-format=github | tee psalm.log || true
+ # If any warnings are found, print a message and exit with a failure code
+ if grep -q "warning" psalm.log; then
+ echo "Warnings detected in Psalm output. Failing build."
+ exit 1
+ fi
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 2184c47d..9c2caaa4 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -51,4 +51,4 @@ jobs:
NEO4J_ADDRESS: "http://localhost:7474"
NEO4J_USERNAME: "neo4j"
NEO4J_PASSWORD: "password"
- run: vendor/bin/phpunit --configuration phpunit.dist.xml
+ run: vendor/bin/phpunit --configuration phpunit.dist.xml ./tests
diff --git a/.github/workflows/testaura.yml b/.github/workflows/testaura.yml
index d08d5bfa..f0dabef4 100644
--- a/.github/workflows/testaura.yml
+++ b/.github/workflows/testaura.yml
@@ -41,4 +41,4 @@ jobs:
NEO4J_ADDRESS: ${{ secrets.NEO4J_ADDRESS }}
NEO4J_USERNAME: ${{ secrets.NEO4J_USERNAME }}
NEO4J_PASSWORD: ${{ secrets.NEO4J_PASSWORD }}
- run: vendor/bin/phpunit --configuration phpunit.dist.xml
+ run: vendor/bin/phpunit --configuration phpunit.dist.xml ./tests
diff --git a/.gitignore b/.gitignore
index ea86c437..6dd2a04a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,8 +13,8 @@ test
#PHP-CS-FIXER
.php-cs-fixer.php
.php-cs-fixer.cache
-
+.phpunit.cache
coverage
-
+xml-coverage
composer.lock
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 23eb4037..5f70cb10 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,13 +1,23 @@
# Use an official PHP image as the base image
FROM php:8.1-cli
-# Install necessary extensions (e.g., for Composer)
-RUN apt-get update && apt-get install -y libpng-dev libjpeg-dev libfreetype6-dev git libzip-dev zip \
+RUN apt-get update && \
+ apt-get install -y \
+ libpng-dev \
+ libjpeg-dev \
+ libfreetype6-dev \
+ git \
+ libzip-dev \
+ zip \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install gd zip
+RUN pecl install xdebug pcov && docker-php-ext-enable xdebug pcov
+
+# Configure Xdebug for coverage
+# RUN echo "xdebug.mode=coverage" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
+
# Set working directory
WORKDIR /var/www
-# Copy the composer.phar file to the container
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
diff --git a/clover.xml b/clover.xml
new file mode 100644
index 00000000..815f7b0f
--- /dev/null
+++ b/clover.xml
@@ -0,0 +1,529 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cobertura.xml b/cobertura.xml
new file mode 100644
index 00000000..7b3d6d47
--- /dev/null
+++ b/cobertura.xml
@@ -0,0 +1,1169 @@
+
+
+
+
+ /home/pratiksha/dev/Neo4j-Client/src
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/composer.json b/composer.json
index c6d022e5..8382c509 100644
--- a/composer.json
+++ b/composer.json
@@ -6,7 +6,6 @@
"psr/http-client": "^1.0",
"ext-json": "*",
"php": "^8.1",
- "nyholm/psr7": "^1.8",
"php-http/discovery": "^1.17"
},
"require-dev": {
@@ -15,7 +14,8 @@
"friendsofphp/php-cs-fixer": "^3.68",
"vimeo/psalm": "^6.8",
"dg/bypass-finals": "^1.9",
- "psalm/plugin-phpunit": "^0.19.2"
+ "psalm/plugin-phpunit": "^0.19.2",
+ "psalm/plugin-mockery": "^1.2"
},
"autoload": {
@@ -52,7 +52,10 @@
"cs": "vendor/bin/php-cs-fixer fix --dry-run --diff --allow-risky=yes",
"cs:fix": "vendor/bin/php-cs-fixer fix --allow-risky=yes",
"psalm": "vendor/bin/psalm --no-cache --show-info=true",
- "phpunit" : "vendor/bin/phpunit"
+ "all-tests" : "vendor/bin/phpunit --configuration=phpunit.xml --testsuite=All ./tests/",
+ "unit-tests" : "vendor/bin/phpunit --configuration=phpunit.xml --testsuite=Unit",
+ "integration-tests" : "vendor/bin/phpunit --configuration=phpunit.xml --testsuite=Integration",
+ "phpunit-with-coverage" : "XDEBUG_MODE=coverage php -d memory_limit=-1 vendor/bin/phpunit --configuration=phpunitCoverage.xml --testsuite=All --coverage-filter=src tests"
}
}
diff --git a/coverage.php b/coverage.php
new file mode 100644
index 00000000..051fb1c0
Binary files /dev/null and b/coverage.php differ
diff --git a/crap4j.xml b/crap4j.xml
new file mode 100644
index 00000000..dccb0a8f
--- /dev/null
+++ b/crap4j.xml
@@ -0,0 +1,906 @@
+
+
+
+ 2025-03-03 08:46:42
+
+ Method Crap Stats
+ 81
+ 0
+ 0
+ 154.05
+ 0
+
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BasicAuthentication
+ __construct
+ __construct(?string $username, ?string $password)
+ __construct(?string $username, ?string $password)
+ 3
+ 3
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BasicAuthentication
+ authenticate
+ authenticate(Psr\Http\Message\RequestInterface $request): Psr\Http\Message\RequestInterface
+ authenticate(Psr\Http\Message\RequestInterface $request): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BasicAuthentication
+ getHeader
+ getHeader(): string
+ getHeader(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BasicAuthentication
+ getType
+ getType(): string
+ getType(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BearerAuthentication
+ __construct
+ __construct(string $token)
+ __construct(string $token)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BearerAuthentication
+ authenticate
+ authenticate(Psr\Http\Message\RequestInterface $request): Psr\Http\Message\RequestInterface
+ authenticate(Psr\Http\Message\RequestInterface $request): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BearerAuthentication
+ getHeader
+ getHeader(): string
+ getHeader(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\BearerAuthentication
+ getType
+ getType(): string
+ getType(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\NoAuth
+ getHeader
+ getHeader(): string
+ getHeader(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\NoAuth
+ getType
+ getType(): string
+ getType(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Authentication
+ Neo4j\QueryAPI\Authentication\NoAuth
+ authenticate
+ authenticate(Psr\Http\Message\RequestInterface $request): Psr\Http\Message\RequestInterface
+ authenticate(Psr\Http\Message\RequestInterface $request): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Configuration
+ __construct
+ __construct(string $baseUri, string $database, bool $includeCounters, Neo4j\QueryAPI\Objects\Bookmarks $bookmarks, Neo4j\QueryAPI\Enums\AccessMode $accessMode)
+ __construct(string $baseUri, string $database, bool $includeCounters, Neo4j\QueryAPI\Objects\Bookmarks $bookmarks, Neo4j\QueryAPI\Enums\AccessMode $accessMode)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Exception
+ Neo4j\QueryAPI\Exception\Neo4jException
+ __construct
+ __construct(array $errorDetails, int $statusCode, ?Throwable $previous)
+ __construct(array $errorDetails, int $statusCode, ?Throwable $previous)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Exception
+ Neo4j\QueryAPI\Exception\Neo4jException
+ fromNeo4jResponse
+ fromNeo4jResponse(array $response, ?Throwable $exception): self
+ fromNeo4jResponse(array $response, ?Throwable $exception): self
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Exception
+ Neo4j\QueryAPI\Exception\Neo4jException
+ getErrorCode
+ getErrorCode(): string
+ getErrorCode(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Exception
+ Neo4j\QueryAPI\Exception\Neo4jException
+ getType
+ getType(): ?string
+ getType(): ?string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Exception
+ Neo4j\QueryAPI\Exception\Neo4jException
+ getSubType
+ getSubType(): ?string
+ getSubType(): ?string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Exception
+ Neo4j\QueryAPI\Exception\Neo4jException
+ getName
+ getName(): ?string
+ getName(): ?string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jQueryAPI
+ __construct
+ __construct(Psr\Http\Client\ClientInterface $client, Neo4j\QueryAPI\ResponseParser $responseParser, Neo4j\QueryAPI\Neo4jRequestFactory $requestFactory, Neo4j\QueryAPI\Configuration $config)
+ __construct(Psr\Http\Client\ClientInterface $client, Neo4j\QueryAPI\ResponseParser $responseParser, Neo4j\QueryAPI\Neo4jRequestFactory $requestFactory, Neo4j\QueryAPI\Configuration $config)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jQueryAPI
+ login
+ login(string $address, ?Neo4j\QueryAPI\Authentication\AuthenticateInterface $auth, ?Neo4j\QueryAPI\Configuration $config): self
+ login(string $address, ?Neo4j\QueryAPI\Authentication\AuthenticateInterface $auth, ?Neo4j\QueryAPI\Configuration $config): self
+ 5
+ 5
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jQueryAPI
+ create
+ create(Neo4j\QueryAPI\Configuration $configuration, Neo4j\QueryAPI\Authentication\AuthenticateInterface $auth): self
+ create(Neo4j\QueryAPI\Configuration $configuration, Neo4j\QueryAPI\Authentication\AuthenticateInterface $auth): self
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jQueryAPI
+ getConfig
+ getConfig(): Neo4j\QueryAPI\Configuration
+ getConfig(): Neo4j\QueryAPI\Configuration
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jQueryAPI
+ run
+ run(string $cypher, array $parameters): Neo4j\QueryAPI\Results\ResultSet
+ run(string $cypher, array $parameters): Neo4j\QueryAPI\Results\ResultSet
+ 2.26
+ 2
+ 60
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jQueryAPI
+ beginTransaction
+ beginTransaction(): Neo4j\QueryAPI\Transaction
+ beginTransaction(): Neo4j\QueryAPI\Transaction
+ 2.01
+ 2
+ 86.67
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jQueryAPI
+ handleRequestException
+ handleRequestException(Psr\Http\Client\RequestExceptionInterface $e): void
+ handleRequestException(Psr\Http\Client\RequestExceptionInterface $e): void
+ 12
+ 3
+ 0
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jRequestFactory
+ __construct
+ __construct(Psr\Http\Message\RequestFactoryInterface $psr17Factory, Psr\Http\Message\StreamFactoryInterface $streamFactory, Neo4j\QueryAPI\Configuration $configuration, Neo4j\QueryAPI\Authentication\AuthenticateInterface $auth)
+ __construct(Psr\Http\Message\RequestFactoryInterface $psr17Factory, Psr\Http\Message\StreamFactoryInterface $streamFactory, Neo4j\QueryAPI\Configuration $configuration, Neo4j\QueryAPI\Authentication\AuthenticateInterface $auth)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jRequestFactory
+ buildRunQueryRequest
+ buildRunQueryRequest(string $cypher, array $parameters): Psr\Http\Message\RequestInterface
+ buildRunQueryRequest(string $cypher, array $parameters): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jRequestFactory
+ buildBeginTransactionRequest
+ buildBeginTransactionRequest(): Psr\Http\Message\RequestInterface
+ buildBeginTransactionRequest(): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jRequestFactory
+ buildCommitRequest
+ buildCommitRequest(string $transactionId, string $clusterAffinity): Psr\Http\Message\RequestInterface
+ buildCommitRequest(string $transactionId, string $clusterAffinity): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jRequestFactory
+ buildRollbackRequest
+ buildRollbackRequest(string $transactionId, string $clusterAffinity): Psr\Http\Message\RequestInterface
+ buildRollbackRequest(string $transactionId, string $clusterAffinity): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jRequestFactory
+ buildTransactionRunRequest
+ buildTransactionRunRequest(string $query, array $parameters, string $transactionId, string $clusterAffinity): Psr\Http\Message\RequestInterface
+ buildTransactionRunRequest(string $query, array $parameters, string $transactionId, string $clusterAffinity): Psr\Http\Message\RequestInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Neo4jRequestFactory
+ createRequest
+ createRequest(string $uri, ?string $cypher, ?array $parameters): Psr\Http\Message\RequestInterface
+ createRequest(string $uri, ?string $cypher, ?array $parameters): Psr\Http\Message\RequestInterface
+ 8
+ 8
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\OGM
+ map
+ map(array $data): mixed
+ map(array $data): mixed
+ 6.02
+ 6
+ 92.31
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\OGM
+ parsePoint
+ parsePoint(string $value): Neo4j\QueryAPI\Objects\Point
+ parsePoint(string $value): Neo4j\QueryAPI\Objects\Point
+ 3
+ 3
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\OGM
+ mapNode
+ mapNode(array $nodeData): Neo4j\QueryAPI\Objects\Node
+ mapNode(array $nodeData): Neo4j\QueryAPI\Objects\Node
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\OGM
+ mapRelationship
+ mapRelationship(array $relationshipData): Neo4j\QueryAPI\Objects\Relationship
+ mapRelationship(array $relationshipData): Neo4j\QueryAPI\Objects\Relationship
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\OGM
+ parseWKT
+ parseWKT(string $wkt): Neo4j\QueryAPI\Objects\Point
+ parseWKT(string $wkt): Neo4j\QueryAPI\Objects\Point
+ 3
+ 3
+ 92.86
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\OGM
+ mapPath
+ mapPath(array $pathData): Neo4j\QueryAPI\Objects\Path
+ mapPath(array $pathData): Neo4j\QueryAPI\Objects\Path
+ 4
+ 4
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\OGM
+ mapProperties
+ mapProperties(array $properties): array
+ mapProperties(array $properties): array
+ 7.29
+ 7
+ 81.82
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Authentication
+ basic
+ basic(string $username, string $password): Neo4j\QueryAPI\Authentication\AuthenticateInterface
+ basic(string $username, string $password): Neo4j\QueryAPI\Authentication\AuthenticateInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Authentication
+ fromEnvironment
+ fromEnvironment(): Neo4j\QueryAPI\Authentication\AuthenticateInterface
+ fromEnvironment(): Neo4j\QueryAPI\Authentication\AuthenticateInterface
+ 3
+ 3
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Authentication
+ bearer
+ bearer(string $token): Neo4j\QueryAPI\Authentication\AuthenticateInterface
+ bearer(string $token): Neo4j\QueryAPI\Authentication\AuthenticateInterface
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Authentication
+ noAuth
+ noAuth(): Neo4j\QueryAPI\Authentication\NoAuth
+ noAuth(): Neo4j\QueryAPI\Authentication\NoAuth
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Bookmarks
+ __construct
+ __construct(array $bookmarks)
+ __construct(array $bookmarks)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Bookmarks
+ addBookmarks
+ addBookmarks(?Neo4j\QueryAPI\Objects\Bookmarks $newBookmarks): void
+ addBookmarks(?Neo4j\QueryAPI\Objects\Bookmarks $newBookmarks): void
+ 2
+ 2
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Bookmarks
+ count
+ count(): int
+ count(): int
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Bookmarks
+ jsonSerialize
+ jsonSerialize(): array
+ jsonSerialize(): array
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Node
+ __construct
+ __construct(array $labels, array $properties)
+ __construct(array $labels, array $properties)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Node
+ toArray
+ toArray(): array
+ toArray(): array
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Path
+ __construct
+ __construct(array $nodes, array $relationships)
+ __construct(array $nodes, array $relationships)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Point
+ __construct
+ __construct(float $x, float $y, float|null $z, int $srid)
+ __construct(float $x, float $y, float|null $z, int $srid)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Point
+ __toString
+ __toString(): string
+ __toString(): string
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\ProfiledQueryPlan
+ __construct
+ __construct(Neo4j\QueryAPI\Objects\ProfiledQueryPlanArguments $arguments, int $dbHits, int $records, bool $hasPageCacheStats, int $pageCacheHits, int $pageCacheMisses, float $pageCacheHitRatio, int $time, string $operatorType, array $children, array $identifiers)
+ __construct(Neo4j\QueryAPI\Objects\ProfiledQueryPlanArguments $arguments, int $dbHits, int $records, bool $hasPageCacheStats, int $pageCacheHits, int $pageCacheMisses, float $pageCacheHitRatio, int $time, string $operatorType, array $children, array $identifiers)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\ProfiledQueryPlanArguments
+ __construct
+ __construct(?int $globalMemory, ?string $plannerImpl, ?int $memory, ?string $stringRepresentation, ?string $runtime, ?int $time, ?int $pageCacheMisses, ?int $pageCacheHits, ?string $runtimeImpl, ?int $version, ?int $dbHits, ?int $batchSize, ?string $details, ?string $plannerVersion, ?string $pipelineInfo, null|string|float $runtimeVersion, ?int $id, ?float $estimatedRows, ?string $planner, ?int $rows)
+ __construct(?int $globalMemory, ?string $plannerImpl, ?int $memory, ?string $stringRepresentation, ?string $runtime, ?int $time, ?int $pageCacheMisses, ?int $pageCacheHits, ?string $runtimeImpl, ?int $version, ?int $dbHits, ?int $batchSize, ?string $details, ?string $plannerVersion, ?string $pipelineInfo, null|string|float $runtimeVersion, ?int $id, ?float $estimatedRows, ?string $planner, ?int $rows)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\Relationship
+ __construct
+ __construct(string $type, array $properties)
+ __construct(string $type, array $properties)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Objects
+ Neo4j\QueryAPI\Objects\ResultCounters
+ __construct
+ __construct(bool $containsUpdates, int $nodesCreated, int $nodesDeleted, int $propertiesSet, int $relationshipsCreated, int $relationshipsDeleted, int $labelsAdded, int $labelsRemoved, int $indexesAdded, int $indexesRemoved, int $constraintsAdded, int $constraintsRemoved, bool $containsSystemUpdates, int $systemUpdates)
+ __construct(bool $containsUpdates, int $nodesCreated, int $nodesDeleted, int $propertiesSet, int $relationshipsCreated, int $relationshipsDeleted, int $labelsAdded, int $labelsRemoved, int $indexesAdded, int $indexesRemoved, int $constraintsAdded, int $constraintsRemoved, bool $containsSystemUpdates, int $systemUpdates)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ __construct
+ __construct(Neo4j\QueryAPI\OGM $ogm)
+ __construct(Neo4j\QueryAPI\OGM $ogm)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ parseRunQueryResponse
+ parseRunQueryResponse(Psr\Http\Message\ResponseInterface $response): Neo4j\QueryAPI\Results\ResultSet
+ parseRunQueryResponse(Psr\Http\Message\ResponseInterface $response): Neo4j\QueryAPI\Results\ResultSet
+ 2
+ 2
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ validateAndDecodeResponse
+ validateAndDecodeResponse(Psr\Http\Message\ResponseInterface $response): array
+ validateAndDecodeResponse(Psr\Http\Message\ResponseInterface $response): array
+ 3
+ 3
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ mapRows
+ mapRows(array $fields, array $values): array
+ mapRows(array $fields, array $values): array
+ 2
+ 2
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ formatOGMOutput
+ formatOGMOutput(mixed $value): mixed
+ formatOGMOutput(mixed $value): mixed
+ 4
+ 4
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ buildCounters
+ buildCounters(array $countersData): Neo4j\QueryAPI\Objects\ResultCounters
+ buildCounters(array $countersData): Neo4j\QueryAPI\Objects\ResultCounters
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ buildBookmarks
+ buildBookmarks(array $bookmarksData): Neo4j\QueryAPI\Objects\Bookmarks
+ buildBookmarks(array $bookmarksData): Neo4j\QueryAPI\Objects\Bookmarks
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ getAccessMode
+ getAccessMode(string $accessModeData): Neo4j\QueryAPI\Enums\AccessMode
+ getAccessMode(string $accessModeData): Neo4j\QueryAPI\Enums\AccessMode
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\ResponseParser
+ buildProfiledQueryPlan
+ buildProfiledQueryPlan(mixed $queryPlanData): ?Neo4j\QueryAPI\Objects\ProfiledQueryPlan
+ buildProfiledQueryPlan(mixed $queryPlanData): ?Neo4j\QueryAPI\Objects\ProfiledQueryPlan
+ 5
+ 5
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ __construct
+ __construct(array $data)
+ __construct(array $data)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ offsetGet
+ offsetGet(mixed $offset): mixed
+ offsetGet(mixed $offset): mixed
+ 2
+ 2
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ offsetExists
+ offsetExists($offset): bool
+ offsetExists($offset): bool
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ offsetSet
+ offsetSet($offset, $value): void
+ offsetSet($offset, $value): void
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ offsetUnset
+ offsetUnset($offset): void
+ offsetUnset($offset): void
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ get
+ get(string $row): mixed
+ get(string $row): mixed
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ count
+ count(): int
+ count(): int
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultRow
+ getIterator
+ getIterator(): Traversable
+ getIterator(): Traversable
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultSet
+ __construct
+ __construct(array $rows, Neo4j\QueryAPI\Objects\Bookmarks $bookmarks, Neo4j\QueryAPI\Enums\AccessMode $accessMode, ?Neo4j\QueryAPI\Objects\ResultCounters $counters, ?Neo4j\QueryAPI\Objects\ProfiledQueryPlan $profiledQueryPlan)
+ __construct(array $rows, Neo4j\QueryAPI\Objects\Bookmarks $bookmarks, Neo4j\QueryAPI\Enums\AccessMode $accessMode, ?Neo4j\QueryAPI\Objects\ResultCounters $counters, ?Neo4j\QueryAPI\Objects\ProfiledQueryPlan $profiledQueryPlan)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultSet
+ getIterator
+ getIterator(): Traversable
+ getIterator(): Traversable
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI\Results
+ Neo4j\QueryAPI\Results\ResultSet
+ count
+ count(): int
+ count(): int
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Transaction
+ __construct
+ __construct(Psr\Http\Client\ClientInterface $client, Neo4j\QueryAPI\ResponseParser $responseParser, Neo4j\QueryAPI\Neo4jRequestFactory $requestFactory, string $clusterAffinity, string $transactionId)
+ __construct(Psr\Http\Client\ClientInterface $client, Neo4j\QueryAPI\ResponseParser $responseParser, Neo4j\QueryAPI\Neo4jRequestFactory $requestFactory, string $clusterAffinity, string $transactionId)
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Transaction
+ run
+ run(string $query, array $parameters): Neo4j\QueryAPI\Results\ResultSet
+ run(string $query, array $parameters): Neo4j\QueryAPI\Results\ResultSet
+ 3.47
+ 3
+ 62.5
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Transaction
+ commit
+ commit(): void
+ commit(): void
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Transaction
+ rollback
+ rollback(): void
+ rollback(): void
+ 1
+ 1
+ 100
+ 0
+
+
+ Neo4j\QueryAPI
+ Neo4j\QueryAPI\Transaction
+ handleRequestException
+ handleRequestException(Psr\Http\Client\RequestExceptionInterface $e): void
+ handleRequestException(Psr\Http\Client\RequestExceptionInterface $e): void
+ 12
+ 3
+ 0
+ 0
+
+
+
diff --git a/docker-compose.yml b/docker-compose.yml
index b5d8dd5a..e8668607 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,5 +1,3 @@
-version: '3.8'
-
services:
# PHP Service
app:
@@ -9,6 +7,9 @@ services:
container_name: php-app
volumes:
- .:/var/www
+ environment:
+ - FAIL_ON_DEPRECATION=1
+ - FAIL_ON_PHPUNIT_DEPRECATION=1
networks:
- mynetwork
diff --git a/phpunit.dist.xml b/phpunit.dist.xml
index a3ab58d8..bf720a43 100644
--- a/phpunit.dist.xml
+++ b/phpunit.dist.xml
@@ -2,23 +2,31 @@
-
+ failOnDeprecation="true"
+ failOnNotice="true"
+ failOnPhpunitDeprecation="true"
+ failOnIncomplete="true"
+ failOnEmptyTestSuite="true"
+ failOnRisky="true"
+ failOnSkipped="true"
+ failOnWarning="true"
+ displayDetailsOnTestsThatTriggerDeprecations="true"
+ displayDetailsOnPhpunitDeprecations="true">
- ./tests
+ ./tests
+
+
+ ./tests/Unit
+
+
+ ./tests/Integration
-
-
+
-
+
diff --git a/phpunit.xml.bak b/phpunit.xml.bak
new file mode 100644
index 00000000..77fcd308
--- /dev/null
+++ b/phpunit.xml.bak
@@ -0,0 +1,22 @@
+
+
+
+
+ ./tests
+
+
+
+
+
+ src
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/phpunitCoverage.xml b/phpunitCoverage.xml
new file mode 100644
index 00000000..41ca73bf
--- /dev/null
+++ b/phpunitCoverage.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+ tests
+
+
+
+
+
+
+
+
+
+
+
+
+ src
+
+
+
+
+
+ src
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/psalm.xml b/psalm.xml
index 25acfe69..271a82d4 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -7,13 +7,13 @@
findUnusedCode="false"
>
-
-
+
+
-
+
-
+
diff --git a/src/Authentication/AuthenticateInterface.php b/src/Authentication/AuthenticateInterface.php
index 1fb5b74d..ce53aeec 100644
--- a/src/Authentication/AuthenticateInterface.php
+++ b/src/Authentication/AuthenticateInterface.php
@@ -4,9 +4,6 @@
use Psr\Http\Message\RequestInterface;
-/**
- * @api
- */
interface AuthenticateInterface
{
public function getHeader(): string;
diff --git a/src/Authentication/BasicAuthentication.php b/src/Authentication/BasicAuthentication.php
index fd48302a..9b91803b 100644
--- a/src/Authentication/BasicAuthentication.php
+++ b/src/Authentication/BasicAuthentication.php
@@ -4,10 +4,7 @@
use Psr\Http\Message\RequestInterface;
-/**
- * @api
- */
-class BasicAuthentication implements AuthenticateInterface
+final class BasicAuthentication implements AuthenticateInterface
{
private string $username;
private string $password;
diff --git a/src/Authentication/BearerAuthentication.php b/src/Authentication/BearerAuthentication.php
index 29c86bd3..c2e62818 100644
--- a/src/Authentication/BearerAuthentication.php
+++ b/src/Authentication/BearerAuthentication.php
@@ -4,14 +4,10 @@
use Psr\Http\Message\RequestInterface;
-/**
- * @api
- */
-class BearerAuthentication implements AuthenticateInterface
+final class BearerAuthentication implements AuthenticateInterface
{
public function __construct(private string $token)
{
- $this->token = $token;
}
#[\Override]
diff --git a/src/Authentication/NoAuth.php b/src/Authentication/NoAuth.php
index 7da1d470..4b1000bb 100644
--- a/src/Authentication/NoAuth.php
+++ b/src/Authentication/NoAuth.php
@@ -4,10 +4,7 @@
use Psr\Http\Message\RequestInterface;
-/**
- * @api
- */
-class NoAuth implements AuthenticateInterface
+final class NoAuth implements AuthenticateInterface
{
#[\Override]
public function getHeader(): string
diff --git a/src/Exception/Neo4jException.php b/src/Exception/Neo4jException.php
index bd4ba314..6550d25a 100644
--- a/src/Exception/Neo4jException.php
+++ b/src/Exception/Neo4jException.php
@@ -4,10 +4,7 @@
use Exception;
-/**
- * @api
- */
-class Neo4jException extends Exception
+final class Neo4jException extends Exception
{
private readonly string $errorCode;
private readonly ?string $errorType;
@@ -38,6 +35,7 @@ public function __construct(
*/
public static function fromNeo4jResponse(array $response, ?\Throwable $exception = null): self
{
+
$errorDetails = $response['errors'][0] ?? ['message' => 'Unknown error', 'code' => 'Neo.UnknownError'];
diff --git a/src/OGM.php b/src/OGM.php
index 5c3c064f..a471e16d 100644
--- a/src/OGM.php
+++ b/src/OGM.php
@@ -36,12 +36,11 @@ public function map(array $data): mixed
private function parsePoint(string $value): Point
{
- // Match SRID and coordinate values
if (preg_match('/SRID=(\d+);POINT(?: Z)? \(([-\d.]+) ([-\d.]+)(?: ([-\d.]+))?\)/', $value, $matches)) {
$srid = (int) $matches[1];
$x = (float) $matches[2];
$y = (float) $matches[3];
- $z = isset($matches[4]) ? (float) $matches[4] : null; // Handle optional Z coordinate
+ $z = isset($matches[4]) ? (float) $matches[4] : null;
return new Point($x, $y, $z, $srid);
}
diff --git a/src/Objects/Authentication.php b/src/Objects/Authentication.php
index df15367c..755609a3 100644
--- a/src/Objects/Authentication.php
+++ b/src/Objects/Authentication.php
@@ -11,9 +11,6 @@ final class Authentication
{
public static function basic(string $username, string $password): AuthenticateInterface
{
- $username = $username ?: 'defaultUsername';
- $password = $password ?: 'defaultPassword';
-
return new BasicAuthentication($username, $password);
}
@@ -29,14 +26,14 @@ public static function fromEnvironment(): AuthenticateInterface
);
}
- public static function noAuth(): AuthenticateInterface
- {
- return new NoAuth();
- }
-
public static function bearer(string $token): AuthenticateInterface
{
return new BearerAuthentication($token);
}
+
+ public static function noAuth(): NoAuth
+ {
+ return new NoAuth();
+ }
}
diff --git a/src/Objects/Bookmarks.php b/src/Objects/Bookmarks.php
index d158552c..138e0dbe 100644
--- a/src/Objects/Bookmarks.php
+++ b/src/Objects/Bookmarks.php
@@ -6,7 +6,7 @@
final class Bookmarks implements \Countable, JsonSerializable
{
- public function __construct(private array $bookmarks)
+ public function __construct(public array $bookmarks)
{
}
@@ -17,12 +17,6 @@ public function addBookmarks(?Bookmarks $newBookmarks): void
}
}
-
- public function getBookmarks(): array
- {
- return $this->bookmarks;
- }
-
#[\Override]
public function count(): int
{
diff --git a/src/Objects/Node.php b/src/Objects/Node.php
index 2bf695b0..28542370 100644
--- a/src/Objects/Node.php
+++ b/src/Objects/Node.php
@@ -6,37 +6,16 @@
* Represents a Neo4j Node with labels and properties.
*/
-class Node
+final class Node
{
/**
- * @var string[] Array of labels for the node.
- */
- private array $labels;
-
- /**
- * @var array Associative array of properties (key-value pairs).
- */
- private array $properties;
-
- /**
- * Node constructor.
+ * Node constructor
*
* @param string[] $labels Array of labels for the node.
* @param array $properties Associative array of properties.
*/
- public function __construct(array $labels, array $properties)
+ public function __construct(public readonly array $labels, public readonly array $properties)
{
- $this->labels = $labels;
- $this->properties = $properties;
- }
-
- /**
- * Get the properties of the node.
- * @return array Associative array of properties.
- */
- public function getProperties(): array
- {
- return $this->properties;
}
/**
@@ -50,4 +29,5 @@ public function toArray(): array
'_properties' => $this->properties,
];
}
+
}
diff --git a/src/Objects/Person.php b/src/Objects/Person.php
deleted file mode 100644
index a6156b09..00000000
--- a/src/Objects/Person.php
+++ /dev/null
@@ -1,20 +0,0 @@
- $properties Associative array of properties for the Person node.
- */
- public function __construct(array $properties)
- {
- parent::__construct(['Person'], $properties);
- }
-}
diff --git a/src/Objects/Point.php b/src/Objects/Point.php
index 9bbda88d..037820cf 100644
--- a/src/Objects/Point.php
+++ b/src/Objects/Point.php
@@ -30,4 +30,5 @@ public function __toString(): string
{
return "SRID={$this->srid};POINT ({$this->x} {$this->y})";
}
+
}
diff --git a/src/Objects/ProfiledQueryPlan.php b/src/Objects/ProfiledQueryPlan.php
index 031861b2..5c81062d 100644
--- a/src/Objects/ProfiledQueryPlan.php
+++ b/src/Objects/ProfiledQueryPlan.php
@@ -5,6 +5,7 @@
final class ProfiledQueryPlan
{
public function __construct(
+ public readonly ProfiledQueryPlanArguments $arguments,
public readonly int $dbHits = 0,
public readonly int $records = 0,
public readonly bool $hasPageCacheStats = false,
@@ -13,7 +14,6 @@ public function __construct(
public readonly float $pageCacheHitRatio = 0.0,
public readonly int $time = 0,
public readonly string $operatorType = '',
- public readonly ProfiledQueryPlanArguments $arguments,
public readonly array $children = [],
public readonly array $identifiers = []
) {
diff --git a/src/Objects/ResultCounters.php b/src/Objects/ResultCounters.php
index ebeb1af7..7deb0b71 100644
--- a/src/Objects/ResultCounters.php
+++ b/src/Objects/ResultCounters.php
@@ -5,96 +5,21 @@
final class ResultCounters
{
public function __construct(
- private readonly bool $containsUpdates = false,
- private readonly int $nodesCreated = 0,
- private readonly int $nodesDeleted = 0,
- private readonly int $propertiesSet = 0,
- private readonly int $relationshipsCreated = 0,
- private readonly int $relationshipsDeleted = 0,
- private readonly int $labelsAdded = 0,
- private readonly int $labelsRemoved = 0,
- private readonly int $indexesAdded = 0,
- private readonly int $indexesRemoved = 0,
- private readonly int $constraintsAdded = 0,
- private readonly int $constraintsRemoved = 0,
- private readonly bool $containsSystemUpdates = false,
- private readonly int $systemUpdates = 0
+ public readonly bool $containsUpdates = false,
+ public readonly int $nodesCreated = 0,
+ public readonly int $nodesDeleted = 0,
+ public readonly int $propertiesSet = 0,
+ public readonly int $relationshipsCreated = 0,
+ public readonly int $relationshipsDeleted = 0,
+ public readonly int $labelsAdded = 0,
+ public readonly int $labelsRemoved = 0,
+ public readonly int $indexesAdded = 0,
+ public readonly int $indexesRemoved = 0,
+ public readonly int $constraintsAdded = 0,
+ public readonly int $constraintsRemoved = 0,
+ public readonly bool $containsSystemUpdates = false,
+ public readonly int $systemUpdates = 0
) {
}
-
-
-
- public function ContainsSystemUpdates(): bool
- {
- return $this->containsSystemUpdates;
- }
-
-
- public function containsUpdates(): bool
- {
- return $this->containsUpdates;
- }
-
- public function getNodesCreated(): int
- {
- return $this->nodesCreated;
- }
-
-
- public function getNodesDeleted(): int
- {
- return $this->nodesDeleted;
- }
-
-
- public function getPropertiesSet(): int
- {
- return $this->propertiesSet;
- }
-
- public function getRelationshipsCreated(): int
- {
- return $this->relationshipsCreated;
- }
-
- public function getRelationshipsDeleted(): int
- {
- return $this->relationshipsDeleted;
- }
-
- public function getLabelsAdded(): int
- {
- return $this->labelsAdded;
- }
-
- public function getIndexesAdded(): int
- {
- return $this->indexesAdded;
- }
-
- public function getIndexesRemoved(): int
- {
- return $this->indexesRemoved;
- }
-
- public function getConstraintsAdded(): int
- {
- return $this->constraintsAdded;
- }
-
- public function getConstraintsRemoved(): int
- {
- return $this->constraintsRemoved;
- }
-
- public function getSystemUpdates(): int
- {
- return $this->systemUpdates;
- }
-
- public function getLabelsRemoved(): int
- {
- return $this->labelsRemoved;
- }
}
diff --git a/src/ResponseParser.php b/src/ResponseParser.php
index 4bc440bc..a018ab50 100644
--- a/src/ResponseParser.php
+++ b/src/ResponseParser.php
@@ -12,7 +12,6 @@
use Neo4j\QueryAPI\Results\ResultRow;
use RuntimeException;
use Neo4j\QueryAPI\Objects\ProfiledQueryPlan;
-use Neo4j\QueryAPI\Objects\Point;
final class ResponseParser
{
@@ -30,7 +29,7 @@ public function parseRunQueryResponse(ResponseInterface $response): ResultSet
$profiledQueryPlan = $this->buildProfiledQueryPlan($data['profiledQueryPlan'] ?? null);
$accessMode = $this->getAccessMode($data['accessMode'] ?? '');
- return new ResultSet($rows, $counters, $bookmarks, $profiledQueryPlan, $accessMode);
+ return new ResultSet($rows, $bookmarks, $accessMode, $counters, $profiledQueryPlan);
}
private function validateAndDecodeResponse(ResponseInterface $response): array
@@ -86,9 +85,6 @@ private function formatOGMOutput(mixed $value): mixed
return $value;
}
-
-
-
private function buildCounters(array $countersData): ResultCounters
{
return new ResultCounters(
@@ -118,24 +114,20 @@ private function getAccessMode(string $accessModeData): AccessMode
return AccessMode::tryFrom($accessModeData) ?? AccessMode::WRITE;
}
- private function buildProfiledQueryPlan(?array $queryPlanData): ?ProfiledQueryPlan
+ private function buildProfiledQueryPlan(mixed $queryPlanData): ?ProfiledQueryPlan
{
- if ($queryPlanData === null || empty($queryPlanData)) {
+ if (! is_array($queryPlanData)) {
return null;
}
- /**
- * @var array $mappedArguments
- */
+ /** @var array $mappedArguments */
$mappedArguments = array_map(function (mixed $value): mixed {
- if (is_array($value) && isset($value['$type']) && isset($value['_value'])) {
+ if (is_array($value) && array_key_exists('$type', $value) && array_key_exists('_value', $value)) {
return $this->ogm->map($value);
}
-
return $value;
}, $queryPlanData['arguments'] ?? []);
-
$queryArguments = new ProfiledQueryPlanArguments(
globalMemory: $mappedArguments['GlobalMemory'] ?? null,
plannerImpl: $mappedArguments['planner-impl'] ?? null,
@@ -158,13 +150,10 @@ private function buildProfiledQueryPlan(?array $queryPlanData): ?ProfiledQueryPl
planner: $mappedArguments['planner'] ?? null,
rows: $mappedArguments['Rows'] ?? null
);
-
- $children = array_map(
- fn (array $child): ?ProfiledQueryPlan => $this->buildProfiledQueryPlan($child),
- $queryPlanData['children'] ?? []
- );
+ $children = array_map(fn (mixed $child): ?ProfiledQueryPlan => $this->buildProfiledQueryPlan($child), $queryPlanData['children'] ?? []);
return new ProfiledQueryPlan(
+ $queryArguments,
$queryPlanData['dbHits'] ?? 0,
$queryPlanData['records'] ?? 0,
$queryPlanData['hasPageCacheStats'] ?? false,
@@ -173,10 +162,9 @@ private function buildProfiledQueryPlan(?array $queryPlanData): ?ProfiledQueryPl
$queryPlanData['pageCacheHitRatio'] ?? 0.0,
$queryPlanData['time'] ?? 0,
$queryPlanData['operatorType'] ?? '',
- $queryArguments,
$children,
$queryPlanData['identifiers'] ?? []
);
- }
+ }
}
diff --git a/src/Results/ResultRow.php b/src/Results/ResultRow.php
index a1378131..9e2fa67c 100644
--- a/src/Results/ResultRow.php
+++ b/src/Results/ResultRow.php
@@ -34,12 +34,6 @@ public function offsetGet(mixed $offset): mixed
return $this->data[$offset];
}
- public function get(string $row): mixed
- {
- return $this->offsetGet($row);
- }
-
-
#[\Override]
public function offsetExists($offset): bool
@@ -58,7 +52,10 @@ public function offsetUnset($offset): void
throw new BadMethodCallException("You can't Unset {$offset}.");
}
-
+ public function get(string $row): mixed
+ {
+ return $this->offsetGet($row);
+ }
#[\Override]
public function count(): int
{
diff --git a/src/Results/ResultSet.php b/src/Results/ResultSet.php
index 67087202..9a373e0f 100644
--- a/src/Results/ResultSet.php
+++ b/src/Results/ResultSet.php
@@ -22,10 +22,10 @@ final class ResultSet implements IteratorAggregate, Countable
*/
public function __construct(
public readonly array $rows,
- public readonly ?ResultCounters $counters = null,
public readonly Bookmarks $bookmarks,
- public readonly ?ProfiledQueryPlan $profiledQueryPlan,
- public readonly AccessMode $accessMode
+ public readonly AccessMode $accessMode,
+ public readonly ?ResultCounters $counters = null,
+ public readonly ?ProfiledQueryPlan $profiledQueryPlan = null
) {
}
@@ -38,11 +38,6 @@ public function getIterator(): Traversable
return new ArrayIterator($this->rows);
}
- public function getQueryCounters(): ?ResultCounters
- {
- return $this->counters;
- }
-
#[\Override]
public function count(): int
@@ -50,18 +45,4 @@ public function count(): int
return count($this->rows);
}
- public function getBookmarks(): ?Bookmarks
- {
- return $this->bookmarks;
- }
-
- public function getAccessMode(): ?AccessMode
- {
- return $this->accessMode;
- }
-
- public function getData(): array
- {
- return $this->rows;
- }
}
diff --git a/src/Transaction.php b/src/Transaction.php
index ec6d45e3..b3115513 100644
--- a/src/Transaction.php
+++ b/src/Transaction.php
@@ -9,23 +9,20 @@
use Psr\Http\Message\ResponseInterface;
use stdClass;
-/**
- * @api
- */
-class Transaction
+final class Transaction
{
public function __construct(
- private ClientInterface $client,
- private ResponseParser $responseParser,
- private Neo4jRequestFactory $requestFactory,
- private string $clusterAffinity,
- private string $transactionId
+ private readonly ClientInterface $client,
+ private readonly ResponseParser $responseParser,
+ private readonly Neo4jRequestFactory $requestFactory,
+ private readonly string $clusterAffinity,
+ private readonly string $transactionId
) {
}
/**
* Execute a Cypher query within the transaction.
- * @api
+ *
* @param string $query The Cypher query to be executed.
* @param array $parameters Parameters for the query.
* @return ResultSet The result rows in ResultSet format.
@@ -50,18 +47,12 @@ public function run(string $query, array $parameters): ResultSet
return $this->responseParser->parseRunQueryResponse($response);
}
- /**
- * @api
- */
public function commit(): void
{
$request = $this->requestFactory->buildCommitRequest($this->transactionId, $this->clusterAffinity);
$this->client->sendRequest($request);
}
- /**
- * @api
- */
public function rollback(): void
{
$request = $this->requestFactory->buildRollbackRequest($this->transactionId, $this->clusterAffinity);
diff --git a/tests/Integration/BookmarksIntegrationTest.php b/tests/Integration/BookmarksIntegrationTest.php
index 58c6d4bb..49fd4ec2 100644
--- a/tests/Integration/BookmarksIntegrationTest.php
+++ b/tests/Integration/BookmarksIntegrationTest.php
@@ -5,6 +5,7 @@
use Neo4j\QueryAPI\Configuration;
use Neo4j\QueryAPI\Exception\Neo4jException;
use Neo4j\QueryAPI\Neo4jQueryAPI;
+use Neo4j\QueryAPI\Results\ResultSet;
use Neo4j\QueryAPI\Tests\CreatesQueryAPI;
use PHPUnit\Framework\TestCase;
use Neo4j\QueryAPI\Objects\Bookmarks;
@@ -26,13 +27,13 @@ public function testCreateBookmarks(): void
{
$result = $this->api->run('CREATE (x:Node {hello: "world"})');
- $bookmarks = $result->getBookmarks() ?? new Bookmarks([]);
+ $bookmarks = $result->bookmarks;
$result = $this->api->run('CREATE (x:Node {hello: "world2"})');
- $bookmarks->addBookmarks($result->getBookmarks());
+ $bookmarks->addBookmarks($result->bookmarks);
$result = $this->api->run('MATCH (x:Node {hello: "world2"}) RETURN x');
- $bookmarks->addBookmarks($result->getBookmarks());
+ $bookmarks->addBookmarks($result->bookmarks);
$this->assertCount(1, $result);
}
diff --git a/tests/Integration/DataTypesIntegrationTest.php b/tests/Integration/DataTypesIntegrationTest.php
index bf83ce28..81c82972 100644
--- a/tests/Integration/DataTypesIntegrationTest.php
+++ b/tests/Integration/DataTypesIntegrationTest.php
@@ -3,6 +3,9 @@
namespace Neo4j\QueryAPI\Tests\Integration;
use Neo4j\QueryAPI\Enums\AccessMode;
+use Neo4j\QueryAPI\Neo4jQueryAPI;
+use Neo4j\QueryAPI\Objects\Authentication;
+use Neo4j\QueryAPI\Objects\Node;
use Neo4j\QueryAPI\Objects\Point;
use Neo4j\QueryAPI\Results\ResultRow;
use Neo4j\QueryAPI\Results\ResultSet;
@@ -30,66 +33,66 @@ public function testWithExactNames(): void
new ResultRow(['n.name' => 'bob1']),
new ResultRow(['n.name' => 'alicy']),
],
- new ResultCounters(),
new Bookmarks([]),
- null,
- AccessMode::WRITE
+ AccessMode::WRITE,
+ new ResultCounters(),
+ null
);
$results = $this->api->run('MATCH (n:Person) WHERE n.name IN $names RETURN n.name', [
'names' => ['bob1', 'alicy']
]);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
- $bookmarks = $results->getBookmarks() ?? new Bookmarks([]);
+ $this->assertEquals($expected->counters, $results->counters);
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
-
public function testWithSingleName(): void
{
$expected = new ResultSet(
[
new ResultRow(['n.name' => 'bob1']),
],
- new ResultCounters(),
new Bookmarks([]),
- null,
- AccessMode::WRITE
+ AccessMode::WRITE,
+ new ResultCounters(),
+ null
);
$results = $this->api->run('MATCH (n:Person) WHERE n.name = $name RETURN n.name LIMIT 1', [
'name' => 'bob1'
]);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
- $bookmarks = $results->getBookmarks() ?: [];
+ $this->assertEquals($expected->counters, $results->counters);
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
+
public function testWithInteger(): void
{
$expected = new ResultSet(
[
new ResultRow(['n.age' => 30]),
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
labelsAdded: 1,
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run('CREATE (n:Person {age: $age}) RETURN n.age', [
'age' => 30
]);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -100,108 +103,112 @@ public function testWithFloat(): void
[
new ResultRow(['n.height' => 1.75]),
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
labelsAdded: 1,
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run('CREATE (n:Person {height: $height}) RETURN n.height', [
'height' => 1.75
]);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
+
public function testWithNull(): void
{
$expected = new ResultSet(
[
new ResultRow(['n.middleName' => null]),
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 0,
labelsAdded: 1,
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run('CREATE (n:Person {middleName: $middleName}) RETURN n.middleName', [
'middleName' => null
]);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
+
public function testWithBoolean(): void
{
$expected = new ResultSet(
[
new ResultRow(['n.isActive' => true]),
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
labelsAdded: 1,
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run('CREATE (n:Person {isActive: $isActive}) RETURN n.isActive', [
'isActive' => true
]);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
+
public function testWithString(): void
{
$expected = new ResultSet(
[
new ResultRow(['n.name' => 'Alice']),
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
labelsAdded: 1,
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run('CREATE (n:Person {name: $name}) RETURN n.name', [
'name' => 'Alice'
]);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
+
public function testWithArray(): void
{
$expected = new ResultSet(
@@ -209,15 +216,15 @@ public function testWithArray(): void
new ResultRow(['n.name' => 'bob1']),
new ResultRow(['n.name' => 'alicy'])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: false,
nodesCreated: 0,
propertiesSet: 0,
labelsAdded: 0,
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -225,27 +232,27 @@ public function testWithArray(): void
['names' => ['bob1', 'alicy']]
);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
- $bookmarks = $results->getBookmarks() ?: [];
+ $this->assertEquals($expected->counters, $results->counters);
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
+
public function testWithDate(): void
{
$expected = new ResultSet(
[
new ResultRow(['n.date' => '2024-12-11T11:00:00Z'])
-
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
- labelsAdded: 1,
+ labelsAdded: 1
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -253,9 +260,9 @@ public function testWithDate(): void
['date' => "2024-12-11T11:00:00Z"]
);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -263,28 +270,27 @@ public function testWithDuration(): void
{
$expected = new ResultSet(
[
- new ResultRow(['n.duration' => 'P14DT16H12M']),
-
+ new ResultRow(['n.duration' => 'P14DT16H12M'])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
- labelsAdded: 1,
+ labelsAdded: 1
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
'CREATE (n:Person {duration: duration($duration)}) RETURN n.duration',
- ['duration' => 'P14DT16H12M'],
+ ['duration' => 'P14DT16H12M']
);
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -292,17 +298,17 @@ public function testWithWGS84_2DPoint(): void
{
$expected = new ResultSet(
[
- new ResultRow(['n.Point' => 'SRID=4326;POINT (1.2 3.4)']),
+ new ResultRow(['n.Point' => 'SRID=4326;POINT (1.2 3.4)'])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
- labelsAdded: 1,
+ labelsAdded: 1
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -311,14 +317,14 @@ public function testWithWGS84_2DPoint(): void
'Point' => [
'longitude' => 1.2,
'latitude' => 3.4,
- 'crs' => 'wgs-84',
- ]]
+ 'crs' => 'wgs-84'
+ ]
+ ]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -326,17 +332,17 @@ public function testWithWGS84_3DPoint(): void
{
$expected = new ResultSet(
[
- new ResultRow(['n.Point' => new Point(1.2, 3.4, 4.2, 4979)]),
+ new ResultRow(['n.Point' => new Point(1.2, 3.4, 4.2, 4979)])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
- labelsAdded: 1,
+ labelsAdded: 1
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -345,14 +351,13 @@ public function testWithWGS84_3DPoint(): void
'longitude' => 1.2,
'latitude' => 3.4,
'height' => 4.2,
- 'srid' => 4979,
+ 'srid' => 4979
]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -360,17 +365,17 @@ public function testWithCartesian2DPoint(): void
{
$expected = new ResultSet(
[
- new ResultRow(['n.Point' => new Point(10.5, 20.7, null, 7203)]),
+ new ResultRow(['n.Point' => new Point(10.5, 20.7, null, 7203)])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
- labelsAdded: 1,
+ labelsAdded: 1
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -378,14 +383,13 @@ public function testWithCartesian2DPoint(): void
[
'x' => 10.5,
'y' => 20.7,
- 'srid' => 7203,
+ 'srid' => 7203
]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -393,17 +397,17 @@ public function testWithCartesian3DPoint(): void
{
$expected = new ResultSet(
[
- new ResultRow(['n.Point' => new Point(10.5, 20.7, 30.9, 9157)]),
+ new ResultRow(['n.Point' => new Point(10.5, 20.7, 30.9, 9157)])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 1,
- labelsAdded: 1,
+ labelsAdded: 1
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -412,14 +416,13 @@ public function testWithCartesian3DPoint(): void
'x' => 10.5,
'y' => 20.7,
'z' => 30.9,
- 'srid' => 9157,
+ 'srid' => 9157
]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -437,19 +440,18 @@ public function testWithNode(): void
'labels' => [
0 => 'Person'
]
-
]
- ]),
+ ])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 1,
propertiesSet: 3,
- labelsAdded: 1,
+ labelsAdded: 1
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -457,14 +459,13 @@ public function testWithNode(): void
[
'name' => 'Ayush',
'age' => 30,
- 'location' => 'New York',
+ 'location' => 'New York'
]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -472,71 +473,67 @@ public function testWithPath(): void
{
$expected = new ResultSet(
[
- new ResultRow(['node1' => [
- 'labels' => ['Person'],
- 'properties' => [
- 'name' => 'A',
+ new ResultRow([
+ 'node1' => [
+ 'labels' => ['Person'],
+ 'properties' => [
+ 'name' => 'A'
+ ]
],
- ],
'node2' => [
'labels' => ['Person'],
'properties' => [
- 'name' => 'B',
- ],
+ 'name' => 'B'
+ ]
],
- 'relationshipTypes' => ['FRIENDS'],
- ]),
+ 'relationshipTypes' => ['FRIENDS']
+ ])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 2,
propertiesSet: 2,
relationshipsCreated: 1,
- labelsAdded: 2,
+ labelsAdded: 2
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
'CREATE (a:Person {name: $name1}), (b:Person {name: $name2}),
- (a)-[r:FRIENDS]->(b)
- RETURN {labels: labels(a), properties: properties(a)} AS node1,
- {labels: labels(b), properties: properties(b)} AS node2,
- collect(type(r)) AS relationshipTypes',
+ (a)-[r:FRIENDS]->(b)
+ RETURN {labels: labels(a), properties: properties(a)} AS node1,
+ {labels: labels(b), properties: properties(b)} AS node2,
+ collect(type(r)) AS relationshipTypes',
[
'name1' => 'A',
- 'name2' => 'B',
+ 'name2' => 'B'
]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
-
public function testWithMap(): void
{
$expected = new ResultSet(
[
- new ResultRow(['map' => [
- 'hello' => 'hello',
- ],
- ]),
+ new ResultRow(['map' => ['hello' => 'hello']])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: false,
nodesCreated: 0,
propertiesSet: 0,
- labelsAdded: 0,
+ labelsAdded: 0
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
@@ -544,10 +541,9 @@ public function testWithMap(): void
[]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
@@ -561,39 +557,39 @@ public function testWithRelationship(): void
'properties' => [
'name' => 'Ayush',
'age' => 30,
- 'location' => 'New York',
- ],
+ 'location' => 'New York'
+ ]
],
'node2' => [
'labels' => ['Person'],
'properties' => [
'name' => 'John',
'age' => 25,
- 'location' => 'Los Angeles',
- ],
+ 'location' => 'Los Angeles'
+ ]
],
- 'relationshipType' => 'FRIEND_OF',
- ]),
+ 'relationshipType' => 'FRIEND_OF'
+ ])
],
+ new Bookmarks([]),
+ AccessMode::WRITE,
new ResultCounters(
containsUpdates: true,
nodesCreated: 2,
propertiesSet: 6,
relationshipsCreated: 1,
- labelsAdded: 2,
+ labelsAdded: 2
),
- new Bookmarks([]),
- null,
- AccessMode::WRITE
+ null
);
$results = $this->api->run(
'CREATE (p1:Person {name: $name1, age: $age1, location: $location1}),
- (p2:Person {name: $name2, age: $age2, location: $location2}),
- (p1)-[r:FRIEND_OF]->(p2)
- RETURN {labels: labels(p1), properties: properties(p1)} AS node1,
- {labels: labels(p2), properties: properties(p2)} AS node2,
- type(r) AS relationshipType',
+ (p2:Person {name: $name2, age: $age2, location: $location2}),
+ (p1)-[r:FRIEND_OF]->(p2)
+ RETURN {labels: labels(p1), properties: properties(p1)} AS node1,
+ {labels: labels(p2), properties: properties(p2)} AS node2,
+ type(r) AS relationshipType',
[
'name1' => 'Ayush',
'age1' => 30,
@@ -604,10 +600,10 @@ public function testWithRelationship(): void
]
);
-
- $this->assertEquals($expected->getQueryCounters(), $results->getQueryCounters());
+ $this->assertEquals($expected->counters, $results->counters);
$this->assertEquals(iterator_to_array($expected), iterator_to_array($results));
- $bookmarks = $results->getBookmarks() ?: [];
+ $bookmarks = $results->bookmarks;
$this->assertCount(1, $bookmarks);
}
+
}
diff --git a/tests/Integration/Neo4jOGMTest.php b/tests/Integration/Neo4jOGMTest.php
index 635fd74e..06a0541d 100644
--- a/tests/Integration/Neo4jOGMTest.php
+++ b/tests/Integration/Neo4jOGMTest.php
@@ -29,7 +29,7 @@ public function testWithNode(): void
];
$node = $this->ogm->map($nodeData);
- $this->assertEquals('Ayush', $node->getProperties()['name']['_value']);
+ $this->assertEquals('Ayush', $node->properties['name']['_value']);
}
public function testWithSimpleRelationship(): void
@@ -85,7 +85,7 @@ public function testWithPath(): void
$this->assertCount(2, $path->nodes);
$this->assertCount(1, $path->relationships);
- $this->assertEquals('A', $path->nodes[0]->getProperties()['name']['_value']);
- $this->assertEquals('B', $path->nodes[1]->getProperties()['name']['_value']);
+ $this->assertEquals('A', $path->nodes[0]->properties['name']['_value']);
+ $this->assertEquals('B', $path->nodes[1]->properties['name']['_value']);
}
}
diff --git a/tests/Integration/Neo4jQueryAPIIntegrationTest.php b/tests/Integration/Neo4jQueryAPIIntegrationTest.php
index 1dce1520..490d6570 100644
--- a/tests/Integration/Neo4jQueryAPIIntegrationTest.php
+++ b/tests/Integration/Neo4jQueryAPIIntegrationTest.php
@@ -29,9 +29,7 @@ public function setUp(): void
public function testParseRunQueryResponse(): void
{
- $query = 'CREATE (n:TestNode {name: "Test"}) RETURN n';
- $response = $this->api->run($query);
- $bookmarks = $response->getBookmarks() ?? new Bookmarks([]);
+ $response = $this->api->run('CREATE (n:TestNode {name: "Test"}) RETURN n');
$this->assertEquals(new ResultSet(
rows: [
@@ -48,7 +46,7 @@ public function testParseRunQueryResponse(): void
propertiesSet: 1,
labelsAdded: 1
),
- bookmarks: $bookmarks,
+ bookmarks: $response->bookmarks,
profiledQueryPlan: null,
accessMode: AccessMode::WRITE
), $response);
@@ -71,10 +69,10 @@ private function initializeApi(): Neo4jQueryAPI
public function testCounters(): void
{
$result = $this->api->run('CREATE (x:Node {hello: "world"})');
- $queryCounters = $result->getQueryCounters();
+ $queryCounters = $result->counters;
$this->assertNotNull($queryCounters);
- $this->assertEquals(1, $queryCounters->getNodesCreated());
+ $this->assertEquals(1, $queryCounters->nodesCreated);
}
private function clearDatabase(): void
diff --git a/tests/Integration/Neo4jTransactionIntegrationTest.php b/tests/Integration/Neo4jTransactionIntegrationTest.php
index 9033ba83..30dd4163 100644
--- a/tests/Integration/Neo4jTransactionIntegrationTest.php
+++ b/tests/Integration/Neo4jTransactionIntegrationTest.php
@@ -10,10 +10,7 @@
use PHPUnit\Framework\TestCase;
use RuntimeException;
-/**
- * @api
- */
-class Neo4jTransactionIntegrationTest extends TestCase
+final class Neo4jTransactionIntegrationTest extends TestCase
{
use CreatesQueryAPI;
diff --git a/tests/Integration/ProfiledQueryPlanIntegrationTest.php b/tests/Integration/ProfiledQueryPlanIntegrationTest.php
index 922e8f95..2b39a2e0 100644
--- a/tests/Integration/ProfiledQueryPlanIntegrationTest.php
+++ b/tests/Integration/ProfiledQueryPlanIntegrationTest.php
@@ -2,6 +2,19 @@
namespace Neo4j\QueryAPI\Tests\Integration;
+use Neo4j\QueryAPI\Configuration;
+use Neo4j\QueryAPI\ResponseParser;
+use Neo4j\QueryAPI\OGM;
+use Neo4j\QueryAPI\Neo4jRequestFactory;
+use GuzzleHttp\Client;
+use GuzzleHttp\Handler\MockHandler;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Response;
+use Http\Discovery\Psr17Factory;
+use Neo4j\QueryAPI\Neo4jQueryAPI;
+use Neo4j\QueryAPI\Objects\Authentication;
+use Neo4j\QueryAPI\Objects\ProfiledQueryPlan;
+use Neo4j\QueryAPI\Results\ResultSet;
use Neo4j\QueryAPI\Tests\CreatesQueryAPI;
use PHPUnit\Framework\TestCase;
@@ -72,4 +85,75 @@ public function testProfileCreateFriendsQueryExistence(): void
$result = $this->api->run($query);
$this->assertNotNull($result->profiledQueryPlan, "Profiled query plan not found");
}
+
+ public function testProfileCreateKnowsBidirectionalRelationships(): void
+ {
+ $query = "
+ PROFILE UNWIND range(1, 100) AS i
+ UNWIND range(1, 100) AS j
+ MATCH (a:Person {id: i}), (b:Person {id: j})
+ WHERE a.id < b.id AND rand() < 0.1
+ CREATE (a)-[:KNOWS]->(b), (b)-[:KNOWS]->(a);
+ ";
+
+ $result = $this->api->run($query);
+ $this->assertNotNull($result->profiledQueryPlan, "profiled query plan not found");
+ $body = file_get_contents(__DIR__ . '/../resources/responses/complex-query-profile.json');
+ if ($body === false) {
+ throw new \UnexpectedValueException('Could not find complex query profile');
+ }
+ $mockSack = new MockHandler([
+ new Response(200, [], $body),
+ ]);
+
+ $handler = HandlerStack::create($mockSack);
+ $client = new Client(['handler' => $handler]);
+ $auth = Authentication::fromEnvironment();
+
+ $api = new Neo4jQueryAPI(
+ $client,
+ new ResponseParser(new OGM()),
+ new Neo4jRequestFactory(
+ new Psr17Factory(),
+ new Psr17Factory(),
+ new Configuration('ABC'),
+ $auth
+ ),
+ new Configuration('ABC'),
+ );
+
+ $result = $api->run($query);
+
+ $plan = $result->profiledQueryPlan;
+ $this->assertNotNull($plan, "The result of the query should not be null.");
+
+ $expected = require __DIR__ . '/../resources/expected/complex-query-profile.php';
+
+ $this->assertEquals($expected->profiledQueryPlan, $plan, "Profiled query plan does not match the expected value.");
+ }
+ public function testProfileCreateActedInRelationships(): void
+ {
+ $query = "
+ PROFILE UNWIND range(1, 50) AS i
+ MATCH (p:Person {id: i}), (m:Movie {year: 2000 + i})
+ WHERE p.job = 'Artist'
+ CREATE (p)-[:ACTED_IN]->(m);
+ ";
+
+ $result = $this->api->run($query);
+ $this->assertNotNull($result->profiledQueryPlan, "profiled query plan not found");
+ }
+
+ public function testChildQueryPlanExistence(): void
+ {
+ $result = $this->api->run("PROFILE MATCH (n:Person {name: 'Alice'}) RETURN n.name");
+
+ $profiledQueryPlan = $result->profiledQueryPlan;
+ $this->assertNotNull($profiledQueryPlan);
+ $this->assertNotEmpty($profiledQueryPlan->children);
+
+ foreach ($profiledQueryPlan->children as $child) {
+ $this->assertInstanceOf(ProfiledQueryPlan::class, $child);
+ }
+ }
}
diff --git a/tests/Unit/Authentication/BasicAuthenticationUnitTest.php b/tests/Unit/Authentication/BasicAuthenticationUnitTest.php
new file mode 100644
index 00000000..a4903c18
--- /dev/null
+++ b/tests/Unit/Authentication/BasicAuthenticationUnitTest.php
@@ -0,0 +1,46 @@
+auth = new BasicAuthentication('testUser', 'testPass');
+ $this->requestMock = $this->createMock(RequestInterface::class);
+ }
+
+ public function testAuthenticateAddsAuthorizationHeader(): void
+ {
+ $authHeader = 'Basic ' . base64_encode('testUser:testPass');
+
+ $this->requestMock->expects($this->once())
+ ->method('withHeader')
+ ->with('Authorization', $authHeader)
+ ->willReturn($this->requestMock);
+
+ $result = $this->auth->authenticate($this->requestMock);
+ $this->assertSame($this->requestMock, $result);
+ }
+
+ public function testGetHeaderReturnsCorrectValue(): void
+ {
+ $expectedHeader = 'Basic ' . base64_encode('testUser:testPass');
+ $this->assertEquals($expectedHeader, $this->auth->getHeader());
+ }
+
+ public function testGetTypeReturnsBasic(): void
+ {
+ $this->assertEquals('Basic', $this->auth->getType());
+ }
+}
diff --git a/tests/Unit/Authentication/BearerAuthenticationUnitTest.php b/tests/Unit/Authentication/BearerAuthenticationUnitTest.php
new file mode 100644
index 00000000..7a2ed977
--- /dev/null
+++ b/tests/Unit/Authentication/BearerAuthenticationUnitTest.php
@@ -0,0 +1,44 @@
+auth = new BearerAuthentication('testToken');
+ $this->requestMock = $this->createMock(RequestInterface::class);
+ }
+
+ public function testAuthenticateAddsAuthorizationHeader(): void
+ {
+ $authHeader = 'Bearer testToken';
+
+ $this->requestMock->expects($this->once())
+ ->method('withHeader')
+ ->with('Authorization', $authHeader)
+ ->willReturnSelf();
+
+ $result = $this->auth->authenticate($this->requestMock);
+ $this->assertSame($this->requestMock, $result);
+ }
+
+ public function testGetHeaderReturnsCorrectValue(): void
+ {
+ $expectedHeader = 'Bearer testToken';
+ $this->assertEquals($expectedHeader, $this->auth->getHeader());
+ }
+
+ public function testGetTypeReturnsBearer(): void
+ {
+ $this->assertEquals('Bearer', $this->auth->getType());
+ }
+}
diff --git a/tests/Unit/Authentication/NoAuthUnitTest.php b/tests/Unit/Authentication/NoAuthUnitTest.php
new file mode 100644
index 00000000..d20fbf90
--- /dev/null
+++ b/tests/Unit/Authentication/NoAuthUnitTest.php
@@ -0,0 +1,38 @@
+auth = new NoAuth();
+ $this->requestMock = $this->createMock(RequestInterface::class);
+ }
+
+ public function testAuthenticateReturnsUnmodifiedRequest(): void
+ {
+ $this->assertSame($this->requestMock, $this->auth->authenticate($this->requestMock));
+ }
+
+ public function testGetHeaderReturnsEmptyString(): void
+ {
+ $this->assertEquals('', $this->auth->getHeader());
+ }
+
+ public function testGetTypeReturnsNoAuth(): void
+ {
+ $this->assertEquals('NoAuth', $this->auth->getType());
+ }
+}
diff --git a/tests/Unit/AuthenticationTest.php b/tests/Unit/AuthenticationTest.php
index 07fdab5e..eacea488 100644
--- a/tests/Unit/AuthenticationTest.php
+++ b/tests/Unit/AuthenticationTest.php
@@ -5,10 +5,7 @@
use Neo4j\QueryAPI\Objects\Authentication;
use PHPUnit\Framework\TestCase;
-/**
- * @api
- */
-class AuthenticationTest extends TestCase
+final class AuthenticationTest extends TestCase
{
public function testBearerToken(): void
{
diff --git a/tests/Unit/Neo4jExceptionUnitTest.php b/tests/Unit/Neo4jExceptionUnitTest.php
index caa0bee3..8d15aadf 100644
--- a/tests/Unit/Neo4jExceptionUnitTest.php
+++ b/tests/Unit/Neo4jExceptionUnitTest.php
@@ -6,10 +6,7 @@
use PHPUnit\Framework\TestCase;
use Neo4j\QueryAPI\Exception\Neo4jException;
-/**
- * @api
- */
-class Neo4jExceptionUnitTest extends TestCase
+final class Neo4jExceptionUnitTest extends TestCase
{
/**
* Test the constructor and property initialization.
diff --git a/tests/Unit/Neo4jQueryAPINewUnitTest.php b/tests/Unit/Neo4jQueryAPINewUnitTest.php
new file mode 100644
index 00000000..623c123a
--- /dev/null
+++ b/tests/Unit/Neo4jQueryAPINewUnitTest.php
@@ -0,0 +1,97 @@
+clientMock = $this->createMock(ClientInterface::class);
+ $this->responseParserMock = $this->createMock(ResponseParser::class);
+ $this->requestFactoryMock = $this->createMock(Neo4jRequestFactory::class);
+ $this->configMock = $this->createMock(Configuration::class);
+
+ $this->api = new Neo4jQueryAPI(
+ client: $this->clientMock,
+ responseParser: $this->responseParserMock,
+ requestFactory: $this->requestFactoryMock,
+ config: $this->configMock
+ );
+ }
+
+ public function testLoginCreatesInstance(): void
+ {
+ $apiInstance = Neo4jQueryAPI::login('http://localhost:7474');
+ $this->assertInstanceOf(Neo4jQueryAPI::class, $apiInstance);
+ }
+
+ public function testGetConfigReturnsCorrectConfig(): void
+ {
+ $config = $this->api->getConfig();
+ $this->assertEquals($this->configMock, $config);
+ }
+
+ public function testRunExecutesQueryAndReturnsResultSet(): void
+ {
+ $cypher = "MATCH (n) RETURN n";
+ $parameters = [];
+
+ $mockRequest = $this->createMock(RequestInterface::class);
+ $mockResponse = $this->createMock(ResponseInterface::class);
+ $mockResultSet = $this->createMock(ResultSet::class);
+
+ $this->requestFactoryMock
+ ->method('buildRunQueryRequest')
+ ->willReturn($mockRequest);
+
+ $this->clientMock
+ ->method('sendRequest')
+ ->willReturn($mockResponse);
+ $this->responseParserMock
+ ->method('parseRunQueryResponse')
+ ->willReturn($mockResultSet);
+
+ $result = $this->api->run($cypher, $parameters);
+
+ $this->assertSame($mockResultSet, $result);
+ }
+
+ public function testHandleRequestExceptionThrowsNeo4jException(): void
+ {
+ $this->expectException(Neo4jException::class);
+
+ $mockException = $this->createMock(RequestExceptionInterface::class);
+ $this->invokeMethod($this->api, 'handleRequestException', [$mockException]);
+ }
+
+ private function invokeMethod(Neo4jQueryAPI $object, string $methodName, array $parameters = []): array
+ {
+ $reflection = new \ReflectionClass(get_class($object));
+ $method = $reflection->getMethod($methodName);
+
+ return $method->invokeArgs($object, $parameters);
+ }
+}
diff --git a/tests/Unit/Neo4jQueryAPIUnitTest.php b/tests/Unit/Neo4jQueryAPIUnitTest.php
index 16ca56ae..1080a947 100644
--- a/tests/Unit/Neo4jQueryAPIUnitTest.php
+++ b/tests/Unit/Neo4jQueryAPIUnitTest.php
@@ -4,6 +4,7 @@
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Response;
use http\Client;
use Http\Discovery\Psr17FactoryDiscovery;
use Neo4j\QueryAPI\Neo4jQueryAPI;
@@ -19,20 +20,11 @@
use Psr\Http\Message\StreamInterface;
use RuntimeException;
use Neo4j\QueryAPI\Configuration;
-use Nyholm\Psr7\Response;
-/**
- * @api
- */
-class Neo4jQueryAPIUnitTest extends TestCase
+final class Neo4jQueryAPIUnitTest extends TestCase
{
- /** @psalm-suppress PropertyNotSetInConstructor */
- private OGM $ogm;
-
- /** @psalm-suppress PropertyNotSetInConstructor */
protected string $address;
- /** @psalm-suppress PropertyNotSetInConstructor */
protected ResponseParser $parser;
#[\Override]
@@ -43,8 +35,7 @@ protected function setUp(): void
$address = getenv('NEO4J_ADDRESS');
$this->address = is_string($address) ? $address : '';
- $this->ogm = new OGM();
- $this->parser = new ResponseParser($this->ogm);
+ $this->parser = new ResponseParser(new OGM());
}
public function testCorrectClientSetup(): void
@@ -137,9 +128,9 @@ public function testParseBookmarks(): void
$result = $this->parser->parseRunQueryResponse($mockResponse);
$this->assertInstanceOf(ResultSet::class, $result);
- $bookmarks = $result->getBookmarks();
+ $bookmarks = $result->bookmarks;
$this->assertInstanceOf(Bookmarks::class, $bookmarks);
- $this->assertCount(3, $bookmarks->getBookmarks());
- $this->assertEquals(['bm1', 'bm2', 'bm3'], $bookmarks->getBookmarks());
+ $this->assertCount(3, $bookmarks->bookmarks);
+ $this->assertEquals(['bm1', 'bm2', 'bm3'], $bookmarks->bookmarks);
}
}
diff --git a/tests/Unit/Neo4jRequestFactoryTest.php b/tests/Unit/Neo4jRequestFactoryTest.php
index 08050db0..9c956049 100644
--- a/tests/Unit/Neo4jRequestFactoryTest.php
+++ b/tests/Unit/Neo4jRequestFactoryTest.php
@@ -2,11 +2,10 @@
namespace Neo4j\QueryAPI\Tests\Unit;
-use Exception;
use Neo4j\QueryAPI\Configuration;
-use Nyholm\Psr7\Factory\Psr17Factory;
+use Override;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
-use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\StreamFactoryInterface;
use GuzzleHttp\Psr7\Request;
@@ -15,26 +14,16 @@
use Neo4j\QueryAPI\Objects\Authentication;
use RuntimeException;
-/**
- * @api
- */
-class Neo4jRequestFactoryTest extends TestCase
+final class Neo4jRequestFactoryTest extends TestCase
{
- /** @psalm-suppress PropertyNotSetInConstructor */
- private RequestFactoryInterface&\PHPUnit\Framework\MockObject\MockObject $psr17Factory;
-
- /** @psalm-suppress PropertyNotSetInConstructor */
- private StreamFactoryInterface&\PHPUnit\Framework\MockObject\MockObject $streamFactory;
-
+ private RequestFactoryInterface&MockObject $psr17Factory;
+ private StreamFactoryInterface&MockObject $streamFactory;
private string $address = '';
private string $authHeader = '';
- /**
- * @throws Exception
- */
- #[\Override]
+ #[Override]
protected function setUp(): void
{
parent::setUp();
@@ -48,9 +37,6 @@ protected function setUp(): void
$this->authHeader = $auth->getHeader();
}
- /**
- * Test for buildRunQueryRequest
- */
public function testBuildRunQueryRequest(): void
{
$cypher = 'MATCH (n) RETURN n';
@@ -90,9 +76,6 @@ public function testBuildRunQueryRequest(): void
}
- /**
- * Test for buildBeginTransactionRequest
- */
public function testBuildBeginTransactionRequest(): void
{
$database = 'neo4j';
@@ -119,9 +102,6 @@ public function testBuildBeginTransactionRequest(): void
$this->assertEquals($uri, (string) $request->getUri());
}
- /**
- * Test for buildCommitRequest
- */
public function testBuildCommitRequest(): void
{
$database = 'neo4j';
@@ -149,9 +129,6 @@ public function testBuildCommitRequest(): void
$this->assertEquals($uri, (string) $request->getUri());
}
- /**
- * Test for buildRollbackRequest
- */
public function testBuildRollbackRequest(): void
{
$database = 'neo4j';
@@ -179,9 +156,6 @@ public function testBuildRollbackRequest(): void
$this->assertEquals($uri, (string) $request->getUri());
}
- /**
- * Test for createRequest method with headers and body
- */
public function testCreateRequestWithHeadersAndBody(): void
{
$cypher = 'MATCH (n) RETURN n';
@@ -222,9 +196,6 @@ public function testCreateRequestWithHeadersAndBody(): void
}
- /**
- * Test createRequest without Authorization header
- */
public function testCreateRequestWithoutAuthorizationHeader(): void
{
$cypher = 'MATCH (n) RETURN n';
diff --git a/tests/Unit/OGMUnitTest.php b/tests/Unit/OGMUnitTest.php
new file mode 100644
index 00000000..68028e7a
--- /dev/null
+++ b/tests/Unit/OGMUnitTest.php
@@ -0,0 +1,118 @@
+ogm = new OGM();
+ }
+
+ public function testMapInteger(): void
+ {
+ $data = ['$type' => 'Integer', '_value' => 42];
+ $this->assertSame(42, $this->ogm->map($data));
+ }
+
+ public function testMapFloat(): void
+ {
+ $data = ['$type' => 'Float', '_value' => 3.14];
+ $this->assertSame(3.14, $this->ogm->map($data));
+ }
+
+ public function testMapString(): void
+ {
+ $data = ['$type' => 'String', '_value' => 'hello'];
+ $this->assertSame('hello', $this->ogm->map($data));
+ }
+
+ public function testMapBoolean(): void
+ {
+ $data = ['$type' => 'Boolean', '_value' => true];
+ $this->assertTrue($this->ogm->map($data));
+ }
+
+ public function testMapNull(): void
+ {
+ $data = ['$type' => 'Null', '_value' => null];
+ $this->assertNull($this->ogm->map($data));
+ }
+
+ public function testMapArray(): void
+ {
+ $data = ['$type' => 'List', '_value' => [['$type' => 'Integer', '_value' => 1], ['$type' => 'Integer', '_value' => 2]]];
+ $this->assertSame([1, 2], $this->ogm->map($data));
+ }
+
+ public function testMapNode(): void
+ {
+ $data = [
+ '$type' => 'Node',
+ '_value' => ['_labels' => ['Person'], '_properties' => ['name' => ['$type' => 'String', '_value' => 'Alice']]]
+ ];
+
+ $result = $this->ogm->map($data);
+ $this->assertInstanceOf(Node::class, $result);
+ $this->assertSame(['Person'], $result->labels);
+ $this->assertSame(['name' => 'Alice'], $result->properties);
+ }
+
+ public function testMapRelationship(): void
+ {
+ $data = [
+ '$type' => 'Relationship',
+ '_value' => ['_type' => 'KNOWS', '_properties' => ['since' => ['$type' => 'Integer', '_value' => 2020]]]
+ ];
+
+ $result = $this->ogm->map($data);
+ $this->assertInstanceOf(Relationship::class, $result);
+ $this->assertSame('KNOWS', $result->type);
+ $this->assertSame(['since' => 2020], $result->properties);
+ }
+
+ public function testMapPoint(): void
+ {
+ $data = ['$type' => 'Point', '_value' => 'SRID=4326;POINT (30 10)'];
+ $result = $this->ogm->map($data);
+
+ $this->assertInstanceOf(Point::class, $result);
+ $this->assertSame(30.0, $result->x);
+ $this->assertSame(10.0, $result->y);
+ $this->assertSame(4326, $result->srid);
+ }
+
+ public function testParseWKT(): void
+ {
+ $wkt = 'SRID=4326;POINT (10 20 30)';
+ $result = OGM::parseWKT($wkt);
+
+ $this->assertInstanceOf(Point::class, $result);
+ $this->assertSame(10.0, $result->x);
+ $this->assertSame(20.0, $result->y);
+ $this->assertSame(30.0, $result->z);
+ $this->assertSame(4326, $result->srid);
+ }
+
+ public function testInvalidWKTThrowsException(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ OGM::parseWKT('Invalid WKT String');
+ }
+
+ public function testInvalidPointFormatThrowsException(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->ogm->map(['$type' => 'Point', '_value' => 'Invalid Point Format']);
+ }
+}
diff --git a/tests/Unit/ResponseParserUnitTest.php b/tests/Unit/ResponseParserUnitTest.php
new file mode 100644
index 00000000..bfee3a2b
--- /dev/null
+++ b/tests/Unit/ResponseParserUnitTest.php
@@ -0,0 +1,99 @@
+parser = new ResponseParser($this->createMock(OGM::class));
+ $this->responseMock = $this->createMock(ResponseInterface::class);
+ $this->streamMock = $this->createMock(StreamInterface::class);
+ }
+
+ public function testParseRunQueryResponseThrowsExceptionOnErrorResponse(): void
+ {
+ $this->responseMock = $this->getMockBuilder(ResponseInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->streamMock = $this->getMockBuilder(StreamInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->responseMock->method('getStatusCode')->willReturn(400);
+ $this->responseMock->expects($this->any())->method('getBody')->willReturn($this->streamMock);
+ $this->streamMock->method('__toString')->willReturn(json_encode(["error" => "some error"]));
+
+ $this->expectException(Neo4jException::class);
+ $this->parser->parseRunQueryResponse($this->responseMock);
+ }
+
+
+ public function testParseRunQueryResponseThrowsExceptionOnInvalidData(): void
+ {
+ $this->responseMock->expects($this->once())
+ ->method('getStatusCode')
+ ->willReturn(200);
+
+ $this->responseMock->expects($this->once())
+ ->method('getBody')
+ ->willReturn($this->streamMock);
+
+ $this->streamMock->expects($this->once())
+ ->method('getContents')
+ ->willReturn(json_encode([]));
+
+ $this->expectException(RuntimeException::class);
+
+ $this->parser->parseRunQueryResponse($this->responseMock);
+ }
+
+ public function testParseRunQueryResponseHandlesProfiledQueryPlan(): void
+ {
+ $data = [
+ 'data' => [
+ 'fields' => ['name'],
+ 'values' => [['Neo4j']]
+ ],
+ 'profiledQueryPlan' => [
+ 'operatorType' => 'SomeOperator',
+ 'arguments' => ['planner' => 'IDP'],
+ 'children' => []
+ ],
+ 'accessMode' => 'READ'
+ ];
+
+ $this->responseMock->expects($this->any())->method('getStatusCode')->willReturn(200);
+
+ $this->responseMock->method('getBody')->willReturn($this->streamMock);
+ $this->streamMock->method('getContents')->willReturn(json_encode($data));
+
+ $resultSet = $this->parser->parseRunQueryResponse($this->responseMock);
+
+ $this->assertInstanceOf(ResultSet::class, $resultSet);
+
+ $reflection = new \ReflectionClass($resultSet);
+ $property = $reflection->getProperty('profiledQueryPlan');
+ $profiledQueryPlan = $property->getValue($resultSet);
+
+ $this->assertInstanceOf(ProfiledQueryPlan::class, $profiledQueryPlan);
+ $this->assertEquals('SomeOperator', $profiledQueryPlan->operatorType);
+ }
+
+}
diff --git a/tests/Unit/ResultRowTest.php b/tests/Unit/ResultRowTest.php
index 0fc9ade5..f14f72f7 100644
--- a/tests/Unit/ResultRowTest.php
+++ b/tests/Unit/ResultRowTest.php
@@ -7,10 +7,7 @@
use BadMethodCallException;
use PHPUnit\Framework\TestCase;
-/**
- * @api
- */
-class ResultRowTest extends TestCase
+final class ResultRowTest extends TestCase
{
public function testArrayAccessGet(): void
{
@@ -23,7 +20,6 @@ public function testArrayAccessGet(): void
$this->assertEquals('Bob', $row['name']);
$this->assertEquals(20, $row['age']);
}
- /** @psalm-suppress UnusedVariable */
public function testArrayAccessInvalidKey(): void
{
$row = new ResultRow([
@@ -34,7 +30,7 @@ public function testArrayAccessInvalidKey(): void
$this->expectException(OutOfBoundsException::class);
$this->expectExceptionMessage('Column phone not found.');
- $value = $row['phone'];
+ $row['phone'];
}
public function testArrayAccessSetThrowsException(): void
diff --git a/tests/Unit/Results/ResultRowUnitTest.php b/tests/Unit/Results/ResultRowUnitTest.php
new file mode 100644
index 00000000..57237a47
--- /dev/null
+++ b/tests/Unit/Results/ResultRowUnitTest.php
@@ -0,0 +1,93 @@
+ 'Alice', 'age' => 25];
+ $row = new ResultRow($data);
+
+ $this->assertEquals('Alice', $row->offsetGet('name'));
+ $this->assertEquals(25, $row->offsetGet('age'));
+ }
+
+ public function testOffsetGetThrowsExceptionForInvalidKey(): void
+ {
+ $this->expectException(OutOfBoundsException::class);
+ $this->expectExceptionMessage("Column invalid_key not found.");
+
+ $data = ['name' => 'Alice'];
+ $row = new ResultRow($data);
+
+ $row->offsetGet('invalid_key');
+ }
+
+ public function testOffsetExists(): void
+ {
+ $data = ['name' => 'Alice', 'age' => 25];
+ $row = new ResultRow($data);
+
+ $this->assertTrue($row->offsetExists('name'));
+ $this->assertTrue($row->offsetExists('age'));
+ $this->assertFalse($row->offsetExists('invalid_key'));
+ }
+
+ public function testOffsetSetThrowsException(): void
+ {
+ $this->expectException(BadMethodCallException::class);
+ $this->expectExceptionMessage("You can't set the value of column new_key.");
+
+ $data = ['name' => 'Alice'];
+ $row = new ResultRow($data);
+
+ $row->offsetSet('new_key', 'value');
+ }
+
+ public function testOffsetUnsetThrowsException(): void
+ {
+ $this->expectException(BadMethodCallException::class);
+ $this->expectExceptionMessage("You can't Unset name.");
+
+ $data = ['name' => 'Alice'];
+ $row = new ResultRow($data);
+
+ $row->offsetUnset('name');
+ }
+
+ public function testGetReturnsValue(): void
+ {
+ $data = ['name' => 'Alice', 'age' => 25];
+ $row = new ResultRow($data);
+
+ $this->assertEquals('Alice', $row->get('name'));
+ $this->assertEquals(25, $row->get('age'));
+ }
+
+ public function testCount(): void
+ {
+ $data = ['name' => 'Alice', 'age' => 25];
+ $row = new ResultRow($data);
+
+ $this->assertCount(2, $row);
+ }
+
+ public function testIterator(): void
+ {
+ $data = ['name' => 'Alice', 'age' => 25];
+ $row = new ResultRow($data);
+
+ $values = [];
+ foreach ($row as $key => $value) {
+ $values[$key] = $value;
+ }
+
+ $this->assertEquals($data, $values);
+ }
+}
diff --git a/tests/Unit/TransactionUnitTest.php b/tests/Unit/TransactionUnitTest.php
index 5fac4a1c..c00c2c01 100644
--- a/tests/Unit/TransactionUnitTest.php
+++ b/tests/Unit/TransactionUnitTest.php
@@ -2,102 +2,120 @@
namespace Neo4j\QueryAPI\Tests\Unit;
+use Neo4j\QueryAPI\Transaction;
+use Neo4j\QueryAPI\Exception\Neo4jException;
use Neo4j\QueryAPI\Results\ResultSet;
+use Neo4j\QueryAPI\ResponseParser;
+use Neo4j\QueryAPI\Neo4jRequestFactory;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
-use Neo4j\QueryAPI\Transaction;
-use Neo4j\QueryAPI\Neo4jRequestFactory;
-use Neo4j\QueryAPI\ResponseParser;
use Psr\Http\Client\ClientInterface;
-use Psr\Http\Message\RequestInterface;
+use Psr\Http\Client\RequestExceptionInterface;
+use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\StreamInterface;
-/**
- * @api
- */
-class TransactionUnitTest extends TestCase
+final class TransactionUnitTest extends TestCase
{
- private MockObject $client;
- private MockObject $requestFactory;
- private MockObject $responseParser;
private Transaction $transaction;
-
- private string $transactionId = 'txn123';
- private string $clusterAffinity = 'leader';
+ private MockObject&ClientInterface $clientMock;
+ private MockObject&ResponseParser $responseParserMock;
+ private MockObject&Neo4jRequestFactory $requestFactoryMock;
+ private MockObject&RequestInterface $requestMock;
+ private MockObject&ResponseInterface $responseMock;
+ private string $transactionId = 'tx123';
+ private string $clusterAffinity = 'LEADER';
#[\Override]
protected function setUp(): void
{
- $this->client = $this->createMock(ClientInterface::class);
- $this->requestFactory = $this->createMock(Neo4jRequestFactory::class);
- $this->responseParser = $this->createMock(ResponseParser::class);
+ $this->clientMock = $this->createMock(ClientInterface::class);
+ /** @psalm-suppress InvalidPropertyAssignmentValue */
+ $this->responseParserMock = $this->createMock(ResponseParser::class);
+ /** @psalm-suppress InvalidPropertyAssignmentValue */
+ $this->requestFactoryMock = $this->createMock(Neo4jRequestFactory::class);
+ $this->requestMock = $this->createMock(RequestInterface::class);
+ $this->responseMock = $this->createMock(ResponseInterface::class);
$this->transaction = new Transaction(
- $this->client,
- $this->responseParser,
- $this->requestFactory,
+ $this->clientMock,
+ $this->responseParserMock,
+ $this->requestFactoryMock,
$this->clusterAffinity,
$this->transactionId
);
}
- public function testRunCallsBuildTransactionRunRequest(): void
+ public function testRunExecutesQuerySuccessfully(): void
{
- $query = "CREATE (:Person {name: \$name})";
- $parameters = ['name' => 'Alice'];
+ $query = 'MATCH (n) RETURN n';
+ $parameters = [];
+ $resultSetMock = $this->createMock(ResultSet::class);
- $mockRequest = $this->createMock(RequestInterface::class);
- $mockResponse = $this->createMock(ResponseInterface::class);
- $mockResultSet = $this->createMock(ResultSet::class);
-
- $this->requestFactory->expects($this->once())
+ $this->requestFactoryMock->expects($this->once())
->method('buildTransactionRunRequest')
->with($query, $parameters, $this->transactionId, $this->clusterAffinity)
- ->willReturn($mockRequest);
+ ->willReturn($this->requestMock);
- $this->client->expects($this->once())
+ $this->clientMock->expects($this->once())
->method('sendRequest')
- ->with($mockRequest)
- ->willReturn($mockResponse);
+ ->with($this->requestMock)
+ ->willReturn($this->responseMock);
- $this->responseParser->expects($this->once())
+ $this->responseParserMock->expects($this->once())
->method('parseRunQueryResponse')
- ->with($mockResponse)
- ->willReturn($mockResultSet);
+ ->with($this->responseMock)
+ ->willReturn($resultSetMock);
$result = $this->transaction->run($query, $parameters);
-
- $this->assertSame($mockResultSet, $result);
+ $this->assertInstanceOf(ResultSet::class, $result);
}
- public function testCommitCallsBuildCommitRequest(): void
+
+ public function testHandleRequestExceptionWithoutResponse(): void
{
- $mockRequest = $this->createMock(RequestInterface::class);
+ $exceptionMock = $this->createMock(RequestExceptionInterface::class);
+
+ $reflection = new \ReflectionClass($exceptionMock);
+ $property = $reflection->getParentClass()->getProperty('message');
+ $property->setValue($exceptionMock, 'Request failed');
+
+ $this->expectException(Neo4jException::class);
+ $this->expectExceptionMessage('Request failed');
+
+ $reflection = new \ReflectionClass($this->transaction);
+ $method = $reflection->getMethod('handleRequestException');
+
+ $method->invoke($this->transaction, $exceptionMock);
+ }
+
+
- $this->requestFactory->expects($this->once())
+ public function testCommitSendsCommitRequest(): void
+ {
+ $this->requestFactoryMock->expects($this->once())
->method('buildCommitRequest')
->with($this->transactionId, $this->clusterAffinity)
- ->willReturn($mockRequest);
+ ->willReturn($this->requestMock);
- $this->client->expects($this->once())
+ $this->clientMock->expects($this->once())
->method('sendRequest')
- ->with($mockRequest);
+ ->with($this->requestMock);
$this->transaction->commit();
}
- public function testRollbackCallsBuildRollbackRequest(): void
+ public function testRollbackSendsRollbackRequest(): void
{
- $mockRequest = $this->createMock(RequestInterface::class);
-
- $this->requestFactory->expects($this->once())
+ $this->requestFactoryMock->expects($this->once())
->method('buildRollbackRequest')
->with($this->transactionId, $this->clusterAffinity)
- ->willReturn($mockRequest);
+ ->willReturn($this->requestMock);
- $this->client->expects($this->once())
+ $this->clientMock->expects($this->once())
->method('sendRequest')
- ->with($mockRequest);
+ ->with($this->requestMock);
$this->transaction->rollback();
}
diff --git a/tests/Unit/objects/AuthenticationUnitTest.php b/tests/Unit/objects/AuthenticationUnitTest.php
new file mode 100644
index 00000000..4b1984cb
--- /dev/null
+++ b/tests/Unit/objects/AuthenticationUnitTest.php
@@ -0,0 +1,40 @@
+assertInstanceOf(BasicAuthentication::class, $auth);
+ }
+
+ public function testFromEnvironmentReturnsBasicAuthenticationInstance(): void
+ {
+ putenv('NEO4J_USERNAME=testUser');
+ putenv('NEO4J_PASSWORD=testPass');
+
+ $auth = Authentication::fromEnvironment();
+ $this->assertInstanceOf(BasicAuthentication::class, $auth);
+ }
+
+ public function testNoAuthReturnsNoAuthInstance(): void
+ {
+ $auth = new NoAuth();
+ $this->assertInstanceOf(NoAuth::class, $auth);
+ }
+
+ public function testBearerReturnsBearerAuthenticationInstance(): void
+ {
+ $auth = Authentication::bearer('testToken');
+ $this->assertInstanceOf(BearerAuthentication::class, $auth);
+ }
+}
diff --git a/tests/Unit/objects/BookmarksUnitTest.php b/tests/Unit/objects/BookmarksUnitTest.php
new file mode 100644
index 00000000..dce580a2
--- /dev/null
+++ b/tests/Unit/objects/BookmarksUnitTest.php
@@ -0,0 +1,48 @@
+bookmarks = new Bookmarks(['bookmark1', 'bookmark2']);
+ }
+
+ public function testGetBookmarksReturnsCorrectArray(): void
+ {
+ $bookmarks = $this->bookmarks;
+ $this->assertEquals(['bookmark1', 'bookmark2'], $bookmarks->bookmarks);
+ }
+
+ public function testAddBookmarksMergesUniqueValues(): void
+ {
+ $newBookmarks = new Bookmarks(['bookmark1', 'bookmark2', 'bookmark3']);
+ $this->bookmarks->addBookmarks($newBookmarks);
+
+ $bookmarks = $this->bookmarks;
+ $this->assertEquals(['bookmark1', 'bookmark2', 'bookmark3'], array_values($bookmarks->bookmarks));
+ }
+
+ public function testAddBookmarksDoesNothingWhenNullIsPassed(): void
+ {
+ $this->bookmarks->addBookmarks(null);
+ $bookmarks = $this->bookmarks;
+ $this->assertEquals(['bookmark1', 'bookmark2'], $bookmarks->bookmarks);
+ }
+
+ public function testCountReturnsCorrectNumber(): void
+ {
+ $this->assertEquals(2, $this->bookmarks->count());
+ }
+
+ public function testJsonSerializeReturnsCorrectArray(): void
+ {
+ $this->assertEquals(['bookmark1', 'bookmark2'], $this->bookmarks->jsonSerialize());
+ }
+}
diff --git a/tests/Unit/objects/NodeUnitTest.php b/tests/Unit/objects/NodeUnitTest.php
new file mode 100644
index 00000000..92aaeca6
--- /dev/null
+++ b/tests/Unit/objects/NodeUnitTest.php
@@ -0,0 +1,38 @@
+node = new Node(['Label1', 'Label2'], ['key1' => 'value1', 'key2' => 42]);
+ }
+
+ public function testGetLabelsReturnsCorrectArray(): void
+ {
+ $node = $this->node;
+ $this->assertEquals(['Label1', 'Label2'], $node->labels);
+ }
+
+ public function testGetPropertiesReturnsCorrectArray(): void
+ {
+ $node = $this->node;
+ $this->assertEquals(['key1' => 'value1', 'key2' => 42], $node->properties);
+ }
+
+ public function testToArrayReturnsCorrectStructure(): void
+ {
+ $expected = [
+ '_labels' => ['Label1', 'Label2'],
+ '_properties' => ['key1' => 'value1', 'key2' => 42],
+ ];
+
+ $this->assertEquals($expected, $this->node->toArray());
+ }
+}
diff --git a/tests/Unit/objects/PathUnitTest.php b/tests/Unit/objects/PathUnitTest.php
new file mode 100644
index 00000000..14ccae0c
--- /dev/null
+++ b/tests/Unit/objects/PathUnitTest.php
@@ -0,0 +1,41 @@
+nodes = [
+ new Node(['Person'], ['name' => 'Alice']),
+ new Node(['Person'], ['name' => 'Bob'])
+ ];
+
+ $this->relationships = [
+ new Relationship('KNOWS', ['since' => 2020])
+ ];
+
+ $this->path = new Path($this->nodes, $this->relationships);
+ }
+
+ public function testGetNodesReturnsCorrectArray(): void
+ {
+ $path = $this->path;
+ $this->assertEquals($this->nodes, $path->nodes);
+ }
+
+ public function testGetRelationshipsReturnsCorrectArray(): void
+ {
+ $path = $this->path;
+ $this->assertEquals($this->relationships, $path->relationships);
+ }
+}
diff --git a/tests/Unit/objects/PointUnitTest.php b/tests/Unit/objects/PointUnitTest.php
new file mode 100644
index 00000000..24399a6e
--- /dev/null
+++ b/tests/Unit/objects/PointUnitTest.php
@@ -0,0 +1,45 @@
+point = new Point(1.5, 2.5, 3.5, 4326);
+ }
+
+ public function testGetXReturnsCorrectValue(): void
+ {
+ $point = $this->point;
+ $this->assertEquals(1.5, $point->x);
+ }
+
+ public function testGetYReturnsCorrectValue(): void
+ {
+ $point = $this->point;
+ $this->assertEquals(2.5, $point->y);
+ }
+
+ public function testGetZReturnsCorrectValue(): void
+ {
+ $point = $this->point;
+ $this->assertEquals(3.5, $point->z);
+ }
+
+ public function testGetSridReturnsCorrectValue(): void
+ {
+ $point = $this->point;
+ $this->assertEquals(4326, $point->srid);
+ }
+
+ public function testToStringReturnsCorrectFormat(): void
+ {
+ $this->assertEquals('SRID=4326;POINT (1.5 2.5)', (string) $this->point);
+ }
+}
diff --git a/tests/Unit/objects/RelationshipUnitTest.php b/tests/Unit/objects/RelationshipUnitTest.php
new file mode 100644
index 00000000..d304f374
--- /dev/null
+++ b/tests/Unit/objects/RelationshipUnitTest.php
@@ -0,0 +1,34 @@
+relationship = new Relationship('FRIENDS_WITH', ['since' => 2020]);
+ }
+
+ public function testGetTypeReturnsCorrectType(): void
+ {
+ $relationship = $this->relationship;
+ $this->assertEquals('FRIENDS_WITH', $relationship->type);
+ }
+
+ public function testGetPropertiesReturnsCorrectArray(): void
+ {
+ $relationship = $this->relationship;
+ $this->assertEquals(['since' => 2020], $relationship->properties);
+ }
+
+ public function testEmptyPropertiesByDefault(): void
+ {
+ $relationship = new Relationship('KNOWS');
+ $this->assertEquals([], $relationship->properties);
+ }
+}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index a8977bee..77098c56 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -1,7 +1,6 @@