Skip to content

Commit 861e77b

Browse files
committed
Merge branch 'main' of github.com:laudis-technologies/neo4j-php-client into main
2 parents 15f57c0 + 5134771 commit 861e77b

File tree

7 files changed

+328
-5
lines changed

7 files changed

+328
-5
lines changed

phpunit.coverage.xml.dist

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
33
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
44
>
5+
<php>
6+
<ini name="memory_limit" value="512M" />
7+
</php>
58
<testsuites>
6-
<testsuite name="Neo4j php test suite">
9+
<testsuite name="Neo4j php test suite">
710
<directory>./tests</directory>
811
</testsuite>
912
</testsuites>

src/Network/Bolt/BoltDriver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
use Laudis\Neo4j\Exception\Neo4jException;
2525
use Laudis\Neo4j\Formatter\BoltCypherFormatter;
2626

27+
/**
28+
* @psalm-type ParsedUrl = array{fragment?: string, host: string, pass: string, path?: string, port?: int, query?: string, scheme?: string, user: string}
29+
*/
2730
final class BoltDriver implements DriverInterface
2831
{
2932
/** @var array{fragment?: string, host: string, pass: string, path?: string, port?: int, query?: string, scheme?: string, user: string} */
@@ -35,7 +38,7 @@ final class BoltDriver implements DriverInterface
3538
/**
3639
* BoltConnection constructor.
3740
*
38-
* @param array{fragment?: string, host: string, pass: string, path?: string, port?: int, query?: string, scheme?: string, user: string} $parsedUrl
41+
* @param ParsedUrl $parsedUrl
3942
*/
4043
public function __construct(array $parsedUrl, BoltInjections $injections)
4144
{

src/ParameterHelper.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
final class ParameterHelper
2323
{
24-
public static function asList(iterable $iterable): Sequence
24+
public static function asList(iterable $iterable): Vector
2525
{
2626
return new Vector($iterable);
2727
}
@@ -58,7 +58,7 @@ public static function asParameter($value)
5858
*
5959
* @return Map<array-key, iterable|scalar|stdClass|null>
6060
*/
61-
public static function formatParameters(iterable $parameters): iterable
61+
public static function formatParameters(iterable $parameters): Map
6262
{
6363
/** @var Map<array-key, iterable|scalar|stdClass|null> $tbr */
6464
$tbr = new Map();
@@ -83,7 +83,7 @@ private static function iterableToArray(iterable $value): array
8383
foreach ($value as $key => $val) {
8484
if (is_int($key) || is_string($key)) {
8585
/** @psalm-suppress MixedAssignment */
86-
$tbr[$key] = $val;
86+
$tbr[$key] = self::asParameter($val);
8787
} else {
8888
$msg = 'Iterable parameters must have an integer or string as key values, '.gettype($key).' received.';
8989
throw new InvalidArgumentException($msg);
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Laudis Neo4j package.
7+
*
8+
* (c) Laudis technologies <http://laudis.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Tests\Integration;
15+
16+
use Exception;
17+
use Laudis\Neo4j\Databags\Statement;
18+
use Laudis\Neo4j\Exception\Neo4jException;
19+
use Laudis\Neo4j\Network\Bolt\BoltDriver;
20+
use Laudis\Neo4j\Network\Bolt\BoltInjections;
21+
use PHPUnit\Framework\TestCase;
22+
23+
/**
24+
* @psalm-import-type ParsedUrl from BoltDriver
25+
*/
26+
final class BoltDriverIntegration extends TestCase
27+
{
28+
/**
29+
* @throws Exception
30+
*/
31+
public function testValidHostname(): void
32+
{
33+
/** @var ParsedUrl $parsedUrl */
34+
$parsedUrl = parse_url('bolt://neo4j:test@neo4j-42');
35+
$driver = new BoltDriver($parsedUrl, BoltInjections::create());
36+
$session = $driver->aquireSession();
37+
$results = $session->run([new Statement(<<<'CYPHER'
38+
RETURN 1 AS x
39+
CYPHER, [])]);
40+
self::assertEquals(1, $results->first()->first()->get('x'));
41+
}
42+
43+
/**
44+
* @throws Exception
45+
*/
46+
public function testValidUrl(): void
47+
{
48+
$ip = gethostbyname('neo4j-42');
49+
/** @var ParsedUrl $parsedUrl */
50+
$parsedUrl = parse_url('bolt://neo4j:test@'.$ip);
51+
$driver = new BoltDriver($parsedUrl, BoltInjections::create());
52+
$session = $driver->aquireSession();
53+
$results = $session->run([new Statement(<<<'CYPHER'
54+
RETURN 1 AS x
55+
CYPHER, [])]);
56+
self::assertEquals(1, $results->first()->first()->get('x'));
57+
}
58+
59+
/**
60+
* @throws Exception
61+
*/
62+
public function testInvalid(): void
63+
{
64+
/** @var ParsedUrl $parsedUrl */
65+
$parsedUrl = parse_url('bolt://neo4j:[email protected]');
66+
$driver = new BoltDriver($parsedUrl, BoltInjections::create());
67+
$this->expectException(Neo4jException::class);
68+
$driver->aquireSession();
69+
}
70+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Laudis Neo4j package.
7+
*
8+
* (c) Laudis technologies <http://laudis.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Tests\Unit;
15+
16+
use Bolt\structures\Node;
17+
use Bolt\structures\Path;
18+
use Bolt\structures\UnboundRelationship;
19+
use Laudis\Neo4j\Formatter\BoltCypherFormatter;
20+
use PHPUnit\Framework\TestCase;
21+
use stdClass;
22+
use UnexpectedValueException;
23+
24+
final class BoltCypherFormatterTest extends TestCase
25+
{
26+
private BoltCypherFormatter $formatter;
27+
28+
protected function setUp(): void
29+
{
30+
parent::setUp();
31+
$this->formatter = new BoltCypherFormatter();
32+
}
33+
34+
public function testFormatPath(): void
35+
{
36+
$path = new Path(
37+
[new Node(1, ['a'], ['a' => 1]), new Node(2, ['b'], ['a' => 2]), new Node(3, ['c'], ['a' => 3])],
38+
[new UnboundRelationship(4, 'a', ['d']), new UnboundRelationship(5, 'a', ['e'])],
39+
[1, 2, 3, 4, 5]
40+
);
41+
42+
$results = [
43+
[
44+
$path,
45+
],
46+
[
47+
],
48+
];
49+
$result = $this->formatter->formatResult(['fields' => ['a']], $results);
50+
51+
self::assertEquals(1, $result->count());
52+
self::assertEquals(1, $result->first()->count());
53+
self::assertEquals([
54+
['a' => 1],
55+
[0 => 'd'],
56+
['a' => 2],
57+
[0 => 'e'],
58+
['a' => 3],
59+
], $result->first()->get('a', []));
60+
}
61+
62+
public function testInvalidObject(): void
63+
{
64+
$this->expectException(UnexpectedValueException::class);
65+
$this->expectExceptionMessage('Cannot handle objects without a properties method. Class given: '.stdClass::class);
66+
$this->formatter->formatResult(['fields' => ['a']], [[new stdClass()], []]);
67+
}
68+
69+
public function testResource(): void
70+
{
71+
$resource = fopen('php://temp', 'b');
72+
$this->expectException(UnexpectedValueException::class);
73+
$this->expectExceptionMessage('Did not expect to receive value of type: resource');
74+
$this->formatter->formatResult(['fields' => ['a']], [[$resource], []]);
75+
}
76+
}

tests/Unit/BoltInjectionsTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Laudis Neo4j package.
7+
*
8+
* (c) Laudis technologies <http://laudis.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Tests\Unit;
15+
16+
use Laudis\Neo4j\Network\Bolt\BoltInjections;
17+
use PHPUnit\Framework\TestCase;
18+
19+
final class BoltInjectionsTest extends TestCase
20+
{
21+
public function testConstruct(): void
22+
{
23+
$injections = BoltInjections::create('test');
24+
self::assertEquals('test', $injections->database());
25+
$injections = new BoltInjections('abc');
26+
self::assertEquals('abc', $injections->database());
27+
}
28+
29+
public function testWithDatabase(): void
30+
{
31+
$injections = new BoltInjections('abc');
32+
self::assertEquals('test', $injections->withDatabase('test')->database());
33+
}
34+
}

tests/Unit/ParameterHelperTest.php

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Laudis Neo4j package.
7+
*
8+
* (c) Laudis technologies <http://laudis.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Tests\Unit;
15+
16+
use Ds\Map;
17+
use Ds\Vector;
18+
use InvalidArgumentException;
19+
use Iterator;
20+
use Laudis\Neo4j\ParameterHelper;
21+
use PHPUnit\Framework\TestCase;
22+
use stdClass;
23+
24+
final class ParameterHelperTest extends TestCase
25+
{
26+
/** @var iterable<iterable|scalar|null> */
27+
private static iterable $invalidIterable;
28+
29+
public static function setUpBeforeClass(): void
30+
{
31+
parent::setUpBeforeClass();
32+
self::$invalidIterable = new class() implements Iterator {
33+
private bool $initial = true;
34+
35+
public function current(): int
36+
{
37+
return 1;
38+
}
39+
40+
public function next(): void
41+
{
42+
$this->initial = false;
43+
}
44+
45+
public function key(): stdClass
46+
{
47+
return new stdClass();
48+
}
49+
50+
public function valid(): bool
51+
{
52+
return $this->initial;
53+
}
54+
55+
public function rewind(): void
56+
{
57+
$this->initial = true;
58+
}
59+
};
60+
}
61+
62+
public function testAsList(): void
63+
{
64+
self::assertEquals([1, 2, 3], ParameterHelper::asList([2 => 1, 'a' => 2, 'd' => 3])->toArray());
65+
}
66+
67+
public function testAsMap(): void
68+
{
69+
self::assertEquals([2 => 1, 'a' => 2, 'd' => 3], ParameterHelper::asMap([2 => 1, 'a' => 2, 'd' => 3])->toArray());
70+
}
71+
72+
public function testFormatParameterString(): void
73+
{
74+
self::assertEquals(['a' => 'b', 'c' => 'd'], ParameterHelper::formatParameters([
75+
'a' => 'b',
76+
'c' => 'd',
77+
])->toArray());
78+
}
79+
80+
public function testFormatParameterInteger(): void
81+
{
82+
self::assertEquals([2 => 'b', 3 => 'd'], ParameterHelper::formatParameters([
83+
2 => 'b',
84+
3 => 'd',
85+
])->toArray());
86+
}
87+
88+
public function testFormatParameterVector(): void
89+
{
90+
self::assertEquals(['b', 'd'], ParameterHelper::formatParameters([
91+
'b',
92+
'd',
93+
])->toArray());
94+
}
95+
96+
public function testFormatParameterIterable(): void
97+
{
98+
self::assertEquals([[1, 2]], ParameterHelper::formatParameters([
99+
[1, 2],
100+
])->toArray());
101+
}
102+
103+
public function testFormatParameterInvalidIterable(): void
104+
{
105+
$this->expectException(InvalidArgumentException::class);
106+
ParameterHelper::formatParameters(self::$invalidIterable);
107+
}
108+
109+
public function testFormatParameterInvalidIterable2(): void
110+
{
111+
$this->expectException(InvalidArgumentException::class);
112+
ParameterHelper::formatParameters([
113+
'a' => [
114+
self::$invalidIterable,
115+
],
116+
]);
117+
}
118+
119+
public function testAsParmeterEmptyVector(): void
120+
{
121+
$result = ParameterHelper::asParameter(new Vector());
122+
self::assertIsArray($result);
123+
self::assertCount(0, $result);
124+
}
125+
126+
public function testAsParmeterEmptyMap(): void
127+
{
128+
$result = ParameterHelper::asParameter(new Map());
129+
self::assertInstanceOf(stdClass::class, $result);
130+
}
131+
132+
public function testAsParmeterEmptyArray(): void
133+
{
134+
$result = ParameterHelper::asParameter([]);
135+
self::assertInstanceOf(stdClass::class, $result);
136+
}
137+
}

0 commit comments

Comments
 (0)