diff --git a/tests/end-to-end/ExamplesTest.php b/tests/end-to-end/ExamplesTest.php index 9b63266..92decfc 100644 --- a/tests/end-to-end/ExamplesTest.php +++ b/tests/end-to-end/ExamplesTest.php @@ -10,6 +10,7 @@ namespace WikibaseSolutions\CypherDSL\Tests\EndToEnd; use PHPUnit\Framework\TestCase; +use WikibaseSolutions\CypherDSL\Clauses\SetClause; use WikibaseSolutions\CypherDSL\Expressions\Procedures\Procedure; use WikibaseSolutions\CypherDSL\Query; @@ -262,6 +263,173 @@ public function testMatchClauseExample5(): void $this->assertStringMatchesFormat("MATCH (%s:Movie:Person) RETURN %s.name AS name, %s.title AS title", $query); } + public function testMatchClauseExample6(): void + { + $movie = Query::node(); + $query = Query::new() + ->match( + Query::node('Person')->withProperties(['name' => 'Oliver Stone'])->relationshipTo($movie) + ) + ->returning($movie->property('title')) + ->build(); + + $this->assertStringMatchesFormat("MATCH (:Person {name: 'Oliver Stone'})-->(%s) RETURN %s.title", $query); + } + + public function testMatchClauseExample7(): void + { + $r = Query::relationshipTo(); + $query = Query::new() + ->match(Query::node('Person')->withProperties(['name' => 'Oliver Stone'])->relationship($r, Query::node())) + ->returning($r) + ->build(); + + $this->assertStringMatchesFormat("MATCH (:Person {name: 'Oliver Stone'})-[%s]->() RETURN %s", $query); + } + + public function testMatchClauseExample8(): void + { + $actor = Query::node(); + $query = Query::new() + ->match( + Query::node('Movie') + ->withProperties(['title' => 'Wall Street']) + ->relationshipFrom($actor, 'ACTED_IN') + ) + ->returning($actor->property('name')) + ->build(); + + $this->assertStringMatchesFormat("MATCH (:Movie {title: 'Wall Street'})<-[:ACTED_IN]-(%s) RETURN %s.name", $query); + } + + public function testMatchClauseExample9(): void + { + $person = Query::node(); + $relationship = Query::relationshipFrom()->withTypes(['ACTED_IN', 'DIRECTED']); + $query = Query::new() + ->match( + Query::node('Movie') + ->withProperties(['title' => 'Wall Street']) + ->relationship($relationship, $person) + ) + ->returning($person->property('name')) + ->build(); + + $this->assertStringMatchesFormat("MATCH (:Movie {title: 'Wall Street'})<-[:ACTED_IN|DIRECTED]-(%s) RETURN %s.name", $query); + } + + public function testMatchClauseExample10(): void + { + $actor = Query::node(); + $relationship = Query::relationshipFrom()->withTypes(['ACTED_IN']); + $query = Query::new() + ->match( + Query::node('Movie') + ->withProperties(['title' => 'Wall Street']) + ->relationship($relationship, $actor) + ) + ->returning($relationship->property('role')) + ->build(); + + $this->assertStringMatchesFormat("MATCH (:Movie {title: 'Wall Street'})<-[%s:ACTED_IN]-() RETURN %s.role", $query); + } + + public function testMatchClauseExample11(): void + { + $charlie = Query::node('Person')->withProperties(['name' => 'Charlie Sheen']); + $rob = Query::node('Person')->withProperties(['name' => 'Rob Reiner']); + + $query = Query::new() + ->match([$charlie, $rob]) + ->create( + Query::node() + ->withVariable($rob->getVariable()) + ->relationshipTo( + Query::node()->withVariable($charlie->getVariable()), 'TYPE INCLUDING A SPACE') + ) + ->build(); + + $this->assertStringMatchesFormat("MATCH (%s:Person {name: 'Charlie Sheen'}), (%s:Person {name: 'Rob Reiner'}) CREATE (%s)-[:`TYPE INCLUDING A SPACE`]->(%s)", $query); + } + + public function testMatchClauseExample12(): void + { + $movie = Query::node(); + $director = Query::node(); + + $query = Query::new() + ->match( + Query::node() + ->withProperties(['name' => 'Charlie Sheen']) + ->relationshipTo($movie, 'ACTED_IN') + ->relationshipFrom($director, 'DIRECTED')) + ->returning([$movie->property('title'), $director->property('name')]) + ->build(); + + $this->assertStringMatchesFormat("MATCH ({name: 'Charlie Sheen'})-[:ACTED_IN]->(%s)<-[:DIRECTED]-(%s) RETURN %s.title, %s.name", $query); + } + + public function testMatchClauseExample13(): void + { + $movie = Query::node('Movie'); + $r = Query::relationshipUni()->addType('ACTED_IN')->withMinHops(1)->withMaxHops(3); + + $query = Query::new() + ->match(Query::node()->withProperties(['name' => 'Charlie Sheen'])->relationship($r, $movie)) + ->returning($movie->property('title')) + ->build(); + + $this->assertStringMatchesFormat("MATCH ({name: 'Charlie Sheen'})-[:ACTED_IN*1..3]-(%s:Movie) RETURN %s.title", $query); + } + + public function testMatchClauseExample14(): void + { + $p = Query::node()->withProperties(['name' => 'Michael Douglas'])->relationshipTo(Query::node()); + + $query = Query::new() + ->match($p) + ->returning($p) + ->build(); + + $this->assertStringMatchesFormat("MATCH %s = ({name: 'Michael Douglas'})-->() RETURN %s", $query); + } + + public function testMergeClauseExample1(): void + { + $robert = Query::node('Critic'); + + $query = Query::new() + ->merge($robert) + ->returning($robert) + ->build(); + + $this->assertStringMatchesFormat("MERGE (%s:Critic) RETURN %s", $query); + } + + public function testMergeClauseExample2(): void + { + $keanu = Query::node('Person')->withProperties(['name' => 'Keanu Reeves']); + + $query = Query::new() + ->merge($keanu, (new SetClause())->add($keanu->property('created')->replaceWith(Query::procedure()::raw('timestamp')))) + ->returning([$keanu->property('name'), $keanu->property('created')]) + ->build(); + + $this->assertStringMatchesFormat("MERGE (%s:Person {name: 'Keanu Reeves'}) ON CREATE SET %s.created = timestamp() RETURN %s.name, %s.created", $query); + } + + public function testMergeClauseExample3(): void + { + $keanu = Query::node('Person')->withProperties(['name' => 'Keanu Reeves']); + + $query = Query::new() + ->merge($keanu, null, (new SetClause())->add($keanu->property('created')->replaceWith(Query::procedure()::raw('timestamp')))) + ->returning([$keanu->property('name'), $keanu->property('created')]) + ->build(); + + $this->assertStringMatchesFormat("MERGE (%s:Person {name: 'Keanu Reeves'}) ON MATCH SET %s.created = timestamp() RETURN %s.name, %s.created", $query); + } + public function testOptionalMatchClauseExample1(): void { $movies = Query::node("Movie"); @@ -271,4 +439,42 @@ public function testOptionalMatchClauseExample1(): void $this->assertSame("OPTIONAL MATCH (:Movie)", $query); } + + public function testCombiningClausesExample1(): void + { + $nineties = Query::node("Movie"); + $expression = $nineties->property('released')->gte(1990)->and($nineties->property('released')->lt(2000)); + + $statement = Query::new() + ->match($nineties) + ->where($expression) + ->returning($nineties->property("title")) + ->build(); + + $this->assertStringMatchesFormat("MATCH (%s:Movie) WHERE ((%s.released >= 1990) AND (%s.released < 2000)) RETURN %s.title", $statement); + } + + public function testExpressions1(): void + { + $released = Query::variable("nineties")->property("released"); + $expression = $released->gte(1990)->and($released->lt(2000)); + + $this->assertSame("((nineties.released >= 1990) AND (nineties.released < 2000))", $expression->toQuery()); + } + + public function testExpressions2(): void + { + $name = Query::variable("actor")->property("name"); + $expression = $name->notEquals("Tom Hanks"); + + $this->assertSame("(actor.name <> 'Tom Hanks')", $expression->toQuery()); + } + + public function testExpressions3(): void + { + $released = Query::variable("nineties")->property("released"); + $expression = $released->gte(1990)->and(Query::rawExpression("(nineties IS NOT NULL)")); + + $this->assertSame("((nineties.released >= 1990) AND (nineties IS NOT NULL))", $expression->toQuery()); + } } diff --git a/tests/end-to-end/MoviesTest.php b/tests/end-to-end/MoviesTest.php index da9c9eb..ace97ec 100644 --- a/tests/end-to-end/MoviesTest.php +++ b/tests/end-to-end/MoviesTest.php @@ -24,6 +24,17 @@ */ final class MoviesTest extends TestCase { + public function testFindAllMovies(): void + { + $movie = node("Movie"); + $query = query() + ->match($movie) + ->returning($movie) + ->build(); + + $this->assertStringMatchesFormat("MATCH (%s:Movie) RETURN %s", $query); + } + public function testFindActorNamedTomHanks(): void { $tom = node()->withProperties([ @@ -32,9 +43,10 @@ public function testFindActorNamedTomHanks(): void $query = query() ->match($tom) - ->returning($tom); + ->returning($tom) + ->build(); - $this->assertStringMatchesFormat('MATCH (%s {name: \'Tom Hanks\'}) RETURN %s', $query->toQuery()); + $this->assertStringMatchesFormat("MATCH (%s {name: 'Tom Hanks'}) RETURN %s", $query); } public function testFindTheMovieWithTitleCloudAtlas(): void @@ -45,9 +57,10 @@ public function testFindTheMovieWithTitleCloudAtlas(): void $query = query() ->match($cloudAtlas) - ->returning($cloudAtlas); + ->returning($cloudAtlas) + ->build(); - $this->assertStringMatchesFormat('MATCH (%s {title: \'Cloud Atlas\'}) RETURN %s', $query->toQuery()); + $this->assertStringMatchesFormat("MATCH (%s {title: 'Cloud Atlas'}) RETURN %s", $query); } public function testFind10People(): void @@ -57,9 +70,10 @@ public function testFind10People(): void $query = query() ->match($people) ->returning($people->property('name')) - ->limit(10); + ->limit(10) + ->build(); - $this->assertStringMatchesFormat('MATCH (%s:Person) RETURN %s.name LIMIT 10', $query->toQuery()); + $this->assertStringMatchesFormat("MATCH (%s:Person) RETURN %s.name LIMIT 10", $query); } public function testFindMoviesReleasedInThe1990s(): void @@ -71,51 +85,49 @@ public function testFindMoviesReleasedInThe1990s(): void $nineties->property('released')->gte(1990), $nineties->property('released')->lt(2000), ]) - ->returning($nineties->property('title')); + ->returning($nineties->property('title')) + ->build(); - $this->assertStringMatchesFormat('MATCH (%s:Movie) WHERE ((%s.released >= 1990) AND (%s.released < 2000)) RETURN %s.title', $query->toQuery()); + $this->assertStringMatchesFormat("MATCH (%s:Movie) WHERE ((%s.released >= 1990) AND (%s.released < 2000)) RETURN %s.title", $query); } public function testListAllTomHanksMovies(): void { $movies = node(); - $tom = node('Person')->withProperties([ - 'name' => 'Tom Hanks', - ]); + $tom = node('Person')->withProperties(['name' => 'Tom Hanks']); $query = query() ->match($tom->relationshipTo($movies, 'ACTED_IN')) - ->returning([$tom, $movies]); + ->returning([$tom, $movies]) + ->build(); - $this->assertStringMatchesFormat('MATCH (%s:Person {name: \'Tom Hanks\'})-[:ACTED_IN]->(%s) RETURN %s, %s', $query->toQuery()); + $this->assertStringMatchesFormat("MATCH (%s:Person {name: 'Tom Hanks'})-[:ACTED_IN]->(%s) RETURN %s, %s", $query); } public function testWhoDirectedCloudAtlas(): void { $directors = node(); - $cloudAtlas = node()->withProperties([ - 'title' => 'Cloud Atlas', - ]); + $cloudAtlas = node()->withProperties(['title' => 'Cloud Atlas',]); $query = query() ->match($cloudAtlas->relationshipFrom($directors, 'DIRECTED')) - ->returning($directors->property('name')); + ->returning($directors->property('name')) + ->build(); - $this->assertStringMatchesFormat('MATCH ({title: \'Cloud Atlas\'})<-[:DIRECTED]-(%s) RETURN %s.name', $query->toQuery()); + $this->assertStringMatchesFormat("MATCH ({title: 'Cloud Atlas'})<-[:DIRECTED]-(%s) RETURN %s.name", $query); } public function testTomHanksCoActors(): void { $coActors = node(); - $tom = node('Person')->withProperties([ - 'name' => 'Tom Hanks', - ]); + $tom = node('Person')->withProperties(['name' => 'Tom Hanks']); $query = query() ->match($tom->relationshipTo(node(), 'ACTED_IN')->relationshipFrom($coActors, 'ACTED_IN')) - ->returning($coActors->property('name')); + ->returning($coActors->property('name')) + ->build(); - $this->assertStringMatchesFormat('MATCH (:Person {name: \'Tom Hanks\'})-[:ACTED_IN]->()<-[:ACTED_IN]-(%s) RETURN %s.name', $query->toQuery()); + $this->assertStringMatchesFormat("MATCH (:Person {name: 'Tom Hanks'})-[:ACTED_IN]->()<-[:ACTED_IN]-(%s) RETURN %s.name", $query); } public function testMoviesAndActorsUpTo4HopsAwayFromKevinBacon(): void