From 445c17c273dda3564a15c50723f76efc217f9087 Mon Sep 17 00:00:00 2001 From: Patrick ALLAIN Date: Tue, 23 Feb 2021 08:50:55 +0100 Subject: [PATCH] Integrate children assertion on nodes --- .../api/beta/AbstractEntitiesAssert.java | 15 +- .../neo4j/api/beta/AbstractNodesAssert.java | 160 +++++- .../api/beta/AbstractRelationshipsAssert.java | 66 ++- .../api/beta/ChildrenDriverNodeAssert.java | 57 ++ .../neo4j/api/beta/DriverResultAssert.java | 10 +- .../assertj/neo4j/api/beta/type/DbNode.java | 7 +- .../api/beta/type/loader/LoaderFactory.java | 15 +- .../neo4j/api/beta/type/loader/Queries.java | 4 + .../neo4j/api/beta/util/DbObjectUtils.java | 41 +- .../api/beta/AbstractEntitiesAssertTests.java | 5 +- .../api/beta/AbstractNodesAssertTests.java | 139 ++++- .../AbstractRelationshipsAssertTests.java | 241 ++++++++- .../beta/ChildrenDriverNodeAssertTests.java | 90 ++++ .../api/beta/ChildrenListAssertTests.java | 28 +- .../api/beta/DriverResultAssertTests.java | 49 ++ .../SampleNodesIntegrationTests.java | 4 +- .../assertj/neo4j/api/beta/testing/Bases.java | 57 ++ .../neo4j/api/beta/testing/Builders.java | 7 +- .../neo4j/api/beta/testing/Loaders.java | 11 + .../builders/ConcreteParentAssertBuilder.java | 40 ++ .../testing/builders/NodesLoaderBuilder.java | 69 +++ .../api/beta/type/loader/NodesTests.java | 4 +- .../api/beta/util/DbObjectUtilsTests.java | 47 ++ .../util/NodeComparisonStrategyTests.java | 2 +- src/test/resources/samples/movies.cypher | 507 ++++++++++++++++++ 25 files changed, 1597 insertions(+), 78 deletions(-) create mode 100644 src/main/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssert.java create mode 100644 src/test/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssertTests.java create mode 100644 src/test/java/org/assertj/neo4j/api/beta/testing/Bases.java create mode 100644 src/test/java/org/assertj/neo4j/api/beta/testing/builders/ConcreteParentAssertBuilder.java create mode 100644 src/test/java/org/assertj/neo4j/api/beta/testing/builders/NodesLoaderBuilder.java create mode 100644 src/test/resources/samples/movies.cypher diff --git a/src/main/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssert.java b/src/main/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssert.java index f14ff45..cb23ac3 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssert.java +++ b/src/main/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssert.java @@ -75,26 +75,25 @@ public abstract class AbstractEntitiesAssert selfType, - final DataLoader dataLoader, final List entities, + final Class selfType, + final DataLoader loader, final EntitiesAssertFactory newSelfFactory, final PARENT_ASSERT parentAssert, final ROOT_ASSERT rootAssert) { - super(entities, selfType, (a, c) -> newSelfFactory.create(a, dataLoader, c), parentAssert, rootAssert); + super(entities, selfType, (a, c) -> newSelfFactory.create(a, loader, c), parentAssert, rootAssert); this.recordType = Objects.requireNonNull(recordType); - this.dataLoader = dataLoader; + this.dataLoader = loader; } /** diff --git a/src/main/java/org/assertj/neo4j/api/beta/AbstractNodesAssert.java b/src/main/java/org/assertj/neo4j/api/beta/AbstractNodesAssert.java index 8e51981..ac7cdd1 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/AbstractNodesAssert.java +++ b/src/main/java/org/assertj/neo4j/api/beta/AbstractNodesAssert.java @@ -23,7 +23,10 @@ import org.assertj.neo4j.api.beta.util.DbObjectUtils; import org.assertj.neo4j.api.beta.util.Predicates; +import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.function.Predicate; /** * Abstract assertion on {@link DbNode}. @@ -46,13 +49,166 @@ public abstract class AbstractNodesAssert selfType, + final Class selfType, final List entities, final DataLoader dataLoader, final EntitiesAssertFactory newSelfFactory, final PARENT_ASSERT parentAssert, final ROOT_ASSERT rootAssert) { - super(ObjectType.NODE, selfType, dataLoader, entities, newSelfFactory, parentAssert, rootAssert); + super(ObjectType.NODE, entities, selfType, dataLoader, newSelfFactory, parentAssert, rootAssert); + } + + private static Predicate emptyLabels(final boolean excludeNoLabels, + final Predicate> predicate) { + if (excludeNoLabels) { + return (n) -> !n.getLabels().isEmpty() && predicate.test(n.getLabels()); + } + return n -> n.getLabels().isEmpty() || predicate.test(n.getLabels()); + } + + /** + * Filter nodes having at least one of the provided labels. + *

+ * By default, if a node has no labels, it will be in the actual entities of the created assertion. To change this + * behavior, you can specify use the method {@link #filteredOnLabels(boolean, String...)}. + *

+ * Example: + *


+     * Nodes nodes = new Nodes(driver);
+     * assertThat(nodes)
+     *   .hasSize(14)
+     *   .filteredOnNonEmptyLabels()
+     *   .hasSize(12)
+     * 
+ * + * @return a new assertion + */ + public NEW_SELF filteredOnNonEmptyLabels() { + return filteredOn(n -> !n.getLabels().isEmpty()); + } + + /** + * Filter nodes having at least one of the provided labels. + *

+ * By default, if a node has no labels, it will be in the actual entities of the created assertion. To change this + * behavior, you can specify use the method {@link #filteredOnLabels(boolean, String...)}. + *

+ * Example: + *


+     * Nodes nodes = new Nodes(driver, "Person");
+     * assertThat(nodes)
+     *   .hasSize(14)
+     *   .filteredOnLabels("TeamMember", "TeamOwner")
+     *   .hasSize(9)
+     * 
+ * + * @param labels the labels that any node should have + * @return a new assertion + */ + public NEW_SELF filteredOnLabels(final String... labels) { + return filteredOnLabels(false, labels); + } + + + /** + * Filter nodes having at least one of the provided labels. + *

+ * Example: + *


+     * Nodes nodes = new Nodes(driver, "Person");
+     * assertThat(nodes)
+     *   .hasSize(14)
+     *   .filteredOnLabels(l -> l.startWith("Team"))
+     *   .hasSize(9)
+     * 
+ * + * @param labels the labels that any node should have + * @return a new assertion + */ + public NEW_SELF filteredOnLabels(final boolean excludeNoLabels, final String... labels) { + return filteredOnLabelMatchingAny(l -> Arrays.asList(labels).contains(l), excludeNoLabels); + } + + /** + * Filter nodes having at least one labels matching the predicate. + *

+ * By default, if a node has no labels, it will be in the result list of actual entities. To change this behavior, + * you can specify use the method {@link #filteredOnLabelMatchingAny(Predicate, boolean)}. + *

+ * Example: + *


+     * Nodes nodes = new Nodes(driver, "Person");
+     * assertThat(nodes)
+     *   .hasSize(14)
+     *   .filteredOnAllLabels(l -> l.startWith("Team"))
+     *   .hasSize(9)
+     * 
+ * + * @param predicate the predicate that the label should match + * @return a new assertion + */ + public NEW_SELF filteredOnLabelMatchingAny(final Predicate predicate) { + return filteredOnLabelMatchingAny(predicate, false); + } + + /** + * Filter nodes having at least one labels matching the predicate. + *

+ * Example: + *


+     * Nodes nodes = new Nodes(driver);
+     * assertThat(nodes)
+     *   .hasSize(14)
+     *   .filteredOnAllLabels(l -> l.startWith("Team"), true)
+     *   .hasSize(7)
+     * 
+ * + * @param predicate the predicate that the label should match + * @return a new assertion + */ + public NEW_SELF filteredOnLabelMatchingAny(final Predicate predicate, boolean excludeNoLabels) { + return filteredOn(emptyLabels(excludeNoLabels, (l) -> l.stream().anyMatch(predicate))); + } + + /** + * Filter nodes having all labels matching the predicate. + *

+ * By default, if a node has no labels, it will be in the result list of actual entities. To change this behavior, + * you can specify use the method {@link #filteredOnLabelMatchingAll(Predicate, boolean)}. + *

+ * Example: + *


+     * Nodes nodes = new Nodes(driver, "AssertJ_Team");
+     * assertThat(nodes)
+     *   .hasSize(14)
+     *   .filteredOnAllLabels(l -> l.startWith("AssertJ_"))
+     *   .hasSize(7)
+     * 
+ * + * @param predicate the predicate that the label should match + * @return a new assertion + */ + public NEW_SELF filteredOnLabelMatchingAll(final Predicate predicate) { + return filteredOnLabelMatchingAll(predicate, false); + } + + /** + * Filter nodes having all labels matching the predicate. + *

+ * Example: + *


+     * Nodes nodes = new Nodes(driver, "AssertJ_Team");
+     * assertThat(nodes)
+     *   .hasSize(14)
+     *   .filteredOnAllLabels(l -> l.startWith("AssertJ_"))
+     *   .hasSize(7)
+     * 
+ * + * @param predicate the predicate that the label should match + * @return a new assertion + */ + public NEW_SELF filteredOnLabelMatchingAll(final Predicate predicate, boolean excludeNoLabels) { + return filteredOn(emptyLabels(excludeNoLabels, (l) -> l.stream().allMatch(predicate))); } /** diff --git a/src/main/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssert.java b/src/main/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssert.java index 1b8ad6c..c68f483 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssert.java +++ b/src/main/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssert.java @@ -16,6 +16,9 @@ import org.assertj.neo4j.api.beta.type.DbRelationship; import org.assertj.neo4j.api.beta.type.ObjectType; import org.assertj.neo4j.api.beta.type.loader.DataLoader; +import org.assertj.neo4j.api.beta.type.loader.LoaderFactory; +import org.assertj.neo4j.api.beta.type.loader.Nodes; +import org.assertj.neo4j.api.beta.util.DbObjectUtils; import org.assertj.neo4j.api.beta.util.Predicates; import java.util.Arrays; @@ -38,18 +41,17 @@ public abstract class AbstractRelationshipsAssert, PARENT_ASSERT extends ParentAssert, ROOT_ASSERT> - extends AbstractEntitiesAssert - implements Navigable { + extends AbstractEntitiesAssert { //@formatter:on protected AbstractRelationshipsAssert( final Class selfType, - final List dbRelationships, - final DataLoader dbData, - final EntitiesAssertFactory factory, + final List entities, + final DataLoader loader, + final EntitiesAssertFactory newSelfFactory, final PARENT_ASSERT parentAssert, final ROOT_ASSERT rootAssert) { - super(ObjectType.RELATIONSHIP, selfType, dbData, dbRelationships, factory, parentAssert, rootAssert); + super(ObjectType.RELATIONSHIP, entities, selfType, loader, newSelfFactory, parentAssert, rootAssert); } /** @@ -80,4 +82,56 @@ public SELF haveAnyOfTypes(final String... types) { ); } + /** + * Retrieve all nodes that are the start node of any actual relationships. + *

+ * Example: + *


+     * Relationships relationships = new Relationships(driver, "KNOWS");
+     * assertThat(relationships)
+     *   .startingNodes("Person")
+     *   .haveLabels("TeamMember")
+     * 
+ * + * @param labels + * @return + */ + public ChildrenDriverNodeAssert startingNodes(final String... labels) { + final Nodes nodes = dataLoader.chain(LoaderFactory.nodeByIds(DbObjectUtils.arrayStartNodeIds(actual))); + return new ChildrenDriverNodeAssert<>(nodes.load(), nodes, myself) + .filteredOnLabels(labels) + .withParent(myself); + } + + /** + * Retrieve all nodes that are the end node of any actual relationships. + *

+ * Example: + *


+     * Relationships relationships = new Relationships(driver, "KNOWS");
+     * assertThat(relationships)
+     *   .endingNodes("Person")
+     *   .haveLabels("TeamMember")
+     * 
+ * + * @param labels + * @return + */ + public ChildrenDriverNodeAssert endingNodes(final String... labels) { + final Nodes nodes = dataLoader.chain(LoaderFactory.nodeByIds(DbObjectUtils.arrayEndNodeIds(actual))); + return new ChildrenDriverNodeAssert<>(nodes.load(), nodes, myself) + .filteredOnLabels(labels) + .withParent(myself); + } + + public SELF haveNoStartingNodes(final String... labels) { + startingNodes(labels).isEmpty(); + return myself; + } + + public SELF haveNoEndingNodes(final String... labels) { + endingNodes(labels).isEmpty(); + return myself; + } + } diff --git a/src/main/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssert.java b/src/main/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssert.java new file mode 100644 index 0000000..5f3c153 --- /dev/null +++ b/src/main/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssert.java @@ -0,0 +1,57 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2013-2020 the original author or authors. + */ +package org.assertj.neo4j.api.beta; + +import org.assertj.neo4j.api.beta.type.DbNode; +import org.assertj.neo4j.api.beta.type.DbRelationship; +import org.assertj.neo4j.api.beta.type.loader.DataLoader; + +import java.util.List; +import java.util.Objects; + +/** + * Children assertion on {@link DbRelationship}. + * + * @param the root assertion type + * @param the parent assertion type + * @author Patrick Allain - 02/01/2021 + */ +//@formatter:off +public class ChildrenDriverNodeAssert, ROOT_ASSERT> + extends AbstractNodesAssert, + ChildrenDriverNodeAssert, ROOT_ASSERT>, + PARENT_ASSERT, + ROOT_ASSERT> + implements Adoptable { +//@formatter:on + + protected ChildrenDriverNodeAssert(final List entities, + final DataLoader loader, + final PARENT_ASSERT parentAssert) { + super( + ChildrenDriverNodeAssert.class, + entities, + loader, + ChildrenDriverNodeAssert::new, + Objects.requireNonNull(parentAssert, "The parent assertion cannot be null."), + Objects.requireNonNull(parentAssert.toRootAssert(), "The root assertion cannot be null.") + ); + } + + /** {@inheritDoc} */ + @Override + public > ChildrenDriverNodeAssert withParent(final NEW_PARENT parentAssert) { + return new ChildrenDriverNodeAssert<>(actual, dataLoader, parentAssert); + } + +} diff --git a/src/main/java/org/assertj/neo4j/api/beta/DriverResultAssert.java b/src/main/java/org/assertj/neo4j/api/beta/DriverResultAssert.java index 5d90e78..5bf869e 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/DriverResultAssert.java +++ b/src/main/java/org/assertj/neo4j/api/beta/DriverResultAssert.java @@ -16,6 +16,7 @@ import org.assertj.neo4j.api.beta.error.ShouldObjectBeOfType; import org.assertj.neo4j.api.beta.error.ShouldValueBeInstanceOf; import org.assertj.neo4j.api.beta.error.ShouldValueBeOfType; +import org.assertj.neo4j.api.beta.type.DbNode; import org.assertj.neo4j.api.beta.type.DbObject; import org.assertj.neo4j.api.beta.type.DbRelationship; import org.assertj.neo4j.api.beta.type.DbResult; @@ -26,7 +27,6 @@ import org.assertj.neo4j.api.beta.util.GroupNames; import org.assertj.neo4j.api.beta.util.Predicates; import org.assertj.neo4j.api.beta.util.Utils; -import org.assertj.neo4j.api.beta.util.Wip; import org.neo4j.driver.Result; import java.util.List; @@ -121,10 +121,10 @@ public DriverResultAssert haveValueInstanceOf(final String columnName, final ); } - // FIXME : Create the children for Nodes - public DriverNodesAssert asNodesAssert(final String columnName) { - Wip.TODO(this); - return null; + public ChildrenDriverNodeAssert asNodeAssert(final String columnName) { + haveType(columnName, ObjectType.NODE); + final List entities = columnObjects(columnName, ObjectType.NODE, DbNode.class); + return new ChildrenDriverNodeAssert<>(entities, DataLoader.staticDataLoader(), myself); } public ChildrenDriverRelationshipsAssert asRelationshipAssert(final String columnName) { diff --git a/src/main/java/org/assertj/neo4j/api/beta/type/DbNode.java b/src/main/java/org/assertj/neo4j/api/beta/type/DbNode.java index d62a452..aab9eed 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/type/DbNode.java +++ b/src/main/java/org/assertj/neo4j/api/beta/type/DbNode.java @@ -82,13 +82,8 @@ public static class DbNodeBuilder extends DbEntityBuilder super(DbNodeBuilder.class); } - public DbNodeBuilder label(final String label) { - this.labels.add(label); - return this; - } - public DbNodeBuilder labels(final String... labels) { - Arrays.stream(labels).forEach(this::label); + this.labels.addAll(Arrays.asList(labels)); return this; } diff --git a/src/main/java/org/assertj/neo4j/api/beta/type/loader/LoaderFactory.java b/src/main/java/org/assertj/neo4j/api/beta/type/loader/LoaderFactory.java index 88ff710..26fafa0 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/type/loader/LoaderFactory.java +++ b/src/main/java/org/assertj/neo4j/api/beta/type/loader/LoaderFactory.java @@ -12,6 +12,7 @@ */ package org.assertj.neo4j.api.beta.type.loader; +import org.assertj.neo4j.api.beta.type.DbNode; import org.assertj.neo4j.api.beta.type.DbRelationship; import org.neo4j.driver.Driver; @@ -19,6 +20,8 @@ * Factory for creating new instance of {@link DataLoader}. *

* This interface prevent to expose internal constructor of {@link DataLoader} implementation. + *

+ * FIXME: This will be much more clean if the driver was directly in the Assertions. To be simplify ? * * @author Patrick Allain - 10/02/2021 */ @@ -38,8 +41,18 @@ public interface LoaderFactory> { * @param types the type of relationships * @return a new loader factory instance. */ - static LoaderFactory relationships(String... types) { + static LoaderFactory relationships(final String... types) { return new LoaderFactoryGeneric<>(Queries.relationships(types), RelationshipLoader::new); } + /** + * Create a new {@link LoaderFactory} for {@link DbNode}. + * + * @param ids the ids of the relationships + * @return a new loader factory instance. + */ + static LoaderFactory nodeByIds(final Long... ids) { + return new LoaderFactoryGeneric<>(Queries.nodeByIds(ids), NodeLoader::new); + } + } diff --git a/src/main/java/org/assertj/neo4j/api/beta/type/loader/Queries.java b/src/main/java/org/assertj/neo4j/api/beta/type/loader/Queries.java index 2f507fc..a3c0dd3 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/type/loader/Queries.java +++ b/src/main/java/org/assertj/neo4j/api/beta/type/loader/Queries.java @@ -12,6 +12,7 @@ */ package org.assertj.neo4j.api.beta.type.loader; +import org.assertj.core.util.Maps; import org.neo4j.driver.Query; import java.util.Arrays; @@ -34,4 +35,7 @@ static Query nodes(final String... labels) { return new Query(String.format("MATCH (n %s) RETURN n", queryLabels)); } + static Query nodeByIds(final Long... ids) { + return new Query("MATCH (n) WHERE id(n) IN $ids RETURN n", Maps.newHashMap("ids", Arrays.asList(ids))); + } } diff --git a/src/main/java/org/assertj/neo4j/api/beta/util/DbObjectUtils.java b/src/main/java/org/assertj/neo4j/api/beta/util/DbObjectUtils.java index c7318f2..e8eca21 100644 --- a/src/main/java/org/assertj/neo4j/api/beta/util/DbObjectUtils.java +++ b/src/main/java/org/assertj/neo4j/api/beta/util/DbObjectUtils.java @@ -27,7 +27,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Patrick Allain - 13/02/2021 @@ -136,6 +138,11 @@ public static List havingOutgoingRelationships(final List nodeIds(final List relationships, + final Function function) { + return relationships.stream().map(function).sorted(); + } + /** * For a relationships list, return the starting node ids. *

@@ -145,10 +152,19 @@ public static List havingOutgoingRelationships(final List startNodeIds(final List relationships) { - return relationships.stream() - .map(DbRelationship::getStart) - .sorted() - .collect(Collectors.toList()); + return nodeIds(relationships, DbRelationship::getStart).collect(Collectors.toList()); + } + + /** + * For a relationships list, return the starting node ids. + *

+ * For a relationship, this is the node id where the relationship is starting. + * + * @param relationships the list of relationships + * @return the starting node ids as array + */ + public static Long[] arrayStartNodeIds(final List relationships) { + return nodeIds(relationships, DbRelationship::getStart).toArray(Long[]::new); } /** @@ -160,10 +176,19 @@ public static List startNodeIds(final List relat * @return the starting node ids */ public static List endNodeIds(final List relationships) { - return relationships.stream() - .map(DbRelationship::getEnd) - .sorted() - .collect(Collectors.toList()); + return nodeIds(relationships, DbRelationship::getEnd).collect(Collectors.toList()); + } + + /** + * For a relationships list, return the ending node ids. + *

+ * For a relationship, this is the node id where the relationship is ending. + * + * @param relationships the list of relationships + * @return the starting node ids as array + */ + public static Long[] arrayEndNodeIds(final List relationships) { + return nodeIds(relationships, DbRelationship::getEnd).toArray(Long[]::new); } /** diff --git a/src/test/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssertTests.java b/src/test/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssertTests.java index 7e69966..c69fc45 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssertTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/AbstractEntitiesAssertTests.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import org.neo4j.driver.Query; import java.time.LocalDate; import java.time.LocalDateTime; @@ -38,7 +37,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; /** * @author Patrick Allain - 12/11/2020 @@ -59,9 +57,8 @@ protected ConcreteEntitiesAssert(List entities, DataLoader loade ConcreteEntitiesAssert parent) { super( ObjectType.NODE, - ConcreteEntitiesAssert.class, + entities, ConcreteEntitiesAssert.class, loader, - entities, ConcreteEntitiesAssert::new, parent, rootAssert(parent) diff --git a/src/test/java/org/assertj/neo4j/api/beta/AbstractNodesAssertTests.java b/src/test/java/org/assertj/neo4j/api/beta/AbstractNodesAssertTests.java index 59091f3..d7440eb 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/AbstractNodesAssertTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/AbstractNodesAssertTests.java @@ -31,6 +31,7 @@ import org.neo4j.driver.Driver; import org.neo4j.driver.Query; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -51,6 +52,15 @@ */ class AbstractNodesAssertTests { + private static final List LABELLED_NODE_BUILDERS = Arrays.asList( + Models.node().id(1).labels("lbl-1", "lbl-2"), + Models.node().id(2).labels("lbl-2", "lbl-3", "other"), + Models.node().id(3).labels("lbl-1", "lbl-3", "other"), + Models.node().id(4).labels("lbl-2", "lbl-4"), + Models.node().id(5).labels("other"), + Models.node().id(6) + ); + private static class BaseNodesTests { protected final Nodes dataLoader; @@ -89,6 +99,7 @@ protected LoaderFactory> argQuery(final String query) @AfterEach void tearDown() { + verify(dataLoader).load(); verifyNoMoreInteractions(this.dataLoader); } } @@ -110,7 +121,6 @@ void should_return_a_list_of_nodes_without_ids() { final DriverNodesAssert result = assertions.usingNoEntityIdComparison(); // THEN - verify(dataLoader).load(); assertThat(result.getActual()) .extracting(DbEntity::getId) .doesNotContainNull(); @@ -122,6 +132,123 @@ void should_return_a_list_of_nodes_without_ids() { } } + @Nested + @DisplayName("filteredOnLabels") + class FilteredOnLabelsTests extends BaseNodesTests { + + public FilteredOnLabelsTests() { + super(LABELLED_NODE_BUILDERS.toArray(new DbNode.DbNodeBuilder[0])); + } + + @Test + void should_filter_nodes_having_at_least_one_labels_matching_the_predicate() { + // WHEN + final DriverNodesAssert result = this.assertions.filteredOnLabels("lbl-1"); + + // THEN + assertThat(result.getActual()) + .hasSize(3) + .extracting(DbEntity::getId).contains(1L, 3L, 6L); + } + + @Test + void should_filter_nodes_having_at_least_one_labels_matching_the_predicate_without_no_labels() { + // WHEN + final DriverNodesAssert result = this.assertions.filteredOnLabels(true, "lbl-1"); + + // THEN + assertThat(result.getActual()) + .hasSize(2) + .extracting(DbEntity::getId).contains(1L, 3L); + } + } + + @Nested + @DisplayName("filteredOnNonEmptyLabels") + class FilteredOnNonEmptyLabelsTests extends BaseNodesTests { + + public FilteredOnNonEmptyLabelsTests() { + super(LABELLED_NODE_BUILDERS.toArray(new DbNode.DbNodeBuilder[0])); + } + + @Test + void should_filter_nodes_having_no_labels() { + // WHEN + final DriverNodesAssert result = this.assertions.filteredOnNonEmptyLabels(); + + // THEN + assertThat(result.getActual()) + .hasSize(5) + .extracting(DbEntity::getId).contains(1L, 2L, 3L, 4L, 5L); + } + + } + + @Nested + @DisplayName("filteredOnLabelMatchingAny") + class FilteredOnLabelMatchingAnyTests extends BaseNodesTests { + + public FilteredOnLabelMatchingAnyTests() { + super(LABELLED_NODE_BUILDERS.toArray(new DbNode.DbNodeBuilder[0])); + } + + @Test + void should_filter_nodes_having_at_least_one_labels_matching_the_predicate() { + // WHEN + final DriverNodesAssert result = this.assertions.filteredOnLabelMatchingAny(l -> l.startsWith("lbl-")); + + // THEN + assertThat(result.getActual()) + .hasSize(5) + .extracting(DbEntity::getId).containsExactlyInAnyOrder(1L, 2L, 3L, 4L, 6L); + } + + @Test + void should_filter_nodes_having_at_least_one_labels_matching_the_predicate_without_no_labels() { + // WHEN + final DriverNodesAssert result = this.assertions + .filteredOnLabelMatchingAny(l -> l.startsWith("lbl-"), true); + + // THEN + assertThat(result.getActual()) + .hasSize(4) + .extracting(DbEntity::getId).containsExactlyInAnyOrder(1L, 2L, 3L, 4L); + } + } + + @Nested + @DisplayName("filteredOnLabelMatchingAll") + class FilteredOnLabelMatchingAllTests extends BaseNodesTests { + + public FilteredOnLabelMatchingAllTests() { + super(LABELLED_NODE_BUILDERS.toArray(new DbNode.DbNodeBuilder[0])); + } + + @Test + void should_filter_nodes_having_at_least_one_labels_matching_the_predicate() { + // WHEN + final DriverNodesAssert result = this.assertions + .filteredOnLabelMatchingAll(l -> l.startsWith("lbl-")); + + // THEN + assertThat(result.getActual()) + .hasSize(3) + .extracting(DbEntity::getId).containsExactlyInAnyOrder(1L, 4L, 6L); + } + + @Test + void should_filter_nodes_having_at_least_one_labels_matching_the_predicate_without_no_labels() { + // WHEN + final DriverNodesAssert result = this.assertions + .filteredOnLabelMatchingAll(l -> l.startsWith("lbl-"), true); + + // THEN + assertThat(result.getActual()) + .hasSize(2) + .extracting(DbEntity::getId).containsExactlyInAnyOrder(1L, 4L); + } + } + @Nested @DisplayName("haveLabels") class HaveLabelsTests extends BaseNodesTests { @@ -142,7 +269,6 @@ void should_fail_when_no_labels_provided() { final Throwable throwable = catchThrowable(assertions::haveLabels); // THEN - verify(dataLoader).load(); assertThat(throwable) .isInstanceOf(IllegalArgumentException.class) .hasMessage("The labels to look for should not be null or empty"); @@ -154,7 +280,6 @@ void should_fail_when_iterable_is_empty() { final Throwable throwable = catchThrowable(() -> assertions.haveLabels(Collections.emptyList())); // THEN - verify(dataLoader).load(); assertThat(throwable) .isInstanceOf(IllegalArgumentException.class) .hasMessage("The iterable of values to look for should not be empty"); @@ -166,7 +291,6 @@ void should_fail_when_single_value() { final Throwable throwable = catchThrowable(() -> assertions.haveLabels("missing")); // THEN - verify(dataLoader).load(); assertThat(throwable) .isInstanceOf(AssertionError.class) .hasMessageContainingAll( @@ -182,7 +306,6 @@ void should_pass_when_single_value() { final DriverNodesAssert result = assertions.haveLabels("all"); // THEN - verify(dataLoader).load(); assertThat(result).isSameAs(assertions); } @@ -214,7 +337,6 @@ void should_pass() { assertions.incomingRelationships("KNOWS", "DISCOVER"); // THEN - verify(dataLoader).load(); verify(dataLoader).chain(argQuery("MATCH ()-[r :DISCOVER|KNOWS]->() RETURN r")); assertThat(result.getActual()) @@ -250,7 +372,6 @@ void should_pass() { assertions.outgoingRelationships("KNOWS", "DISCOVER"); // THEN - verify(dataLoader).load(); verify(dataLoader).chain(argQuery("MATCH ()-[r :DISCOVER|KNOWS]->() RETURN r")); assertThat(result.getActual()) @@ -284,7 +405,6 @@ void should_fail() { final Throwable throwable = catchThrowable(() -> assertions.haveNoIncomingRelationships()); // THEN - verify(dataLoader).load(); verify(dataLoader).chain(argQuery("MATCH ()-[r]->() RETURN r")); assertThat(throwable) @@ -310,7 +430,6 @@ void should_pass() { final DriverNodesAssert result = assertions.haveNoIncomingRelationships("KNOWS", "DISCOVER"); // THEN - verify(dataLoader).load(); verify(dataLoader).chain(argQuery("MATCH ()-[r :DISCOVER|KNOWS]->() RETURN r")); assertThat(result).isSameAs(assertions); @@ -343,7 +462,6 @@ void should_fail() { final Throwable throwable = catchThrowable(() -> assertions.haveNoOutgoingRelationships()); // THEN - verify(dataLoader).load(); verify(dataLoader).chain(argQuery("MATCH ()-[r]->() RETURN r")); assertThat(throwable) @@ -369,7 +487,6 @@ void should_pass() { final DriverNodesAssert result = assertions.haveNoOutgoingRelationships("KNOWS", "DISCOVER"); // THEN - verify(dataLoader).load(); verify(dataLoader).chain(argQuery("MATCH ()-[r :DISCOVER|KNOWS]->() RETURN r")); assertThat(result).isSameAs(assertions); diff --git a/src/test/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssertTests.java b/src/test/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssertTests.java index 00dcd2a..9a10ede 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssertTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/AbstractRelationshipsAssertTests.java @@ -12,7 +12,9 @@ */ package org.assertj.neo4j.api.beta; +import org.assertj.neo4j.api.beta.testing.Loaders; import org.assertj.neo4j.api.beta.type.DbEntity; +import org.assertj.neo4j.api.beta.type.DbNode; import org.assertj.neo4j.api.beta.type.DbRelationship; import org.assertj.neo4j.api.beta.type.Models; import org.assertj.neo4j.api.beta.type.loader.DataLoader; @@ -28,14 +30,20 @@ import org.neo4j.driver.Driver; import org.neo4j.driver.Query; +import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; +import static org.assertj.core.api.Assertions.entry; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -68,16 +76,21 @@ void setUp() { } protected void testCase(final List nodes) { + reset(this.dataLoader); when(this.dataLoader.load()).thenReturn(nodes); this.assertions = new DriverRelationshipsAssert(dataLoader); } - protected LoaderFactory> argQuery(final String query) { - return argThat(d -> Objects.equals(d.create(this.driver).query(), new Query(query))); + protected LoaderFactory> argQuery(final String query, + final Entry... params) { + final Map parameters = Arrays.stream(params) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + return argThat(d -> Objects.equals(d.create(this.driver).query(), new Query(query, parameters))); } @AfterEach void tearDown() { + verify(this.dataLoader).load(); verifyNoMoreInteractions(this.dataLoader); } } @@ -192,4 +205,228 @@ void should_pass() { } + @Nested + @DisplayName("startingNodes") + class StartingNodesTests extends BaseRelationshipsTests { + + StartingNodesTests() { + super( + Models.relation().start(11), + Models.relation().start(12), + Models.relation().start(13), + Models.relation().start(14), + Models.relation().start(15), + Models.relation().start(16) + ); + } + + @Test + void should_pass() { + // GIVEN + final DbNode node1 = Models.node().id(11).labels("lbl-1", "lbl-2").build(); + final DbNode node2 = Models.node().id(12).labels("lbl-2", "lbl-3").build(); + final DbNode node3 = Models.node().id(13).labels("lbl-2", "lbl-4").build(); + final DbNode node4 = Models.node().id(14).labels("lbl-3").build(); + final DbNode node5 = Models.node().id(15).labels("lbl-4").build(); + final DbNode node6 = Models.node().id(16).build(); + when(dataLoader.chain(any())).thenReturn(Loaders.nodes(node1, node2, node3, node4, node5, node6)); + + // WHEN + final ChildrenDriverNodeAssert result = + this.assertions.startingNodes("lbl-1", "lbl-3"); + + // THEN + verify(dataLoader).chain( + argQuery("MATCH (n) WHERE id(n) IN $ids RETURN n", + entry("ids", Arrays.asList(11, 12, 13, 14, 15, 16)) + ) + ); + assertThat(result.toParentAssert()).isSameAs(assertions); + assertThat(result.toRootAssert()).isSameAs(assertions.toRootAssert()); + assertThat(result.getActual()) + .hasSize(4) + .extracting(DbEntity::getId).contains(11L, 12L, 14L, 16L); + } + } + + @Nested + @DisplayName("endingNodes") + class EndingNodesTests extends BaseRelationshipsTests { + + EndingNodesTests() { + super( + Models.relation().end(11), + Models.relation().end(12), + Models.relation().end(13), + Models.relation().end(14), + Models.relation().end(15), + Models.relation().end(16) + ); + } + + @Test + void should_pass() { + // GIVEN + final DbNode node1 = Models.node().id(11).labels("lbl-1", "lbl-2").build(); + final DbNode node2 = Models.node().id(12).labels("lbl-2", "lbl-3").build(); + final DbNode node3 = Models.node().id(13).labels("lbl-2", "lbl-4").build(); + final DbNode node4 = Models.node().id(14).labels("lbl-3").build(); + final DbNode node5 = Models.node().id(15).labels("lbl-4").build(); + final DbNode node6 = Models.node().id(16).build(); + when(dataLoader.chain(any())).thenReturn(Loaders.nodes(node1, node2, node3, node4, node5, node6)); + + // WHEN + final ChildrenDriverNodeAssert result = + this.assertions.endingNodes("lbl-1", "lbl-3"); + + // THEN + verify(dataLoader).chain( + argQuery("MATCH (n) WHERE id(n) IN $ids RETURN n", + entry("ids", Arrays.asList(11, 12, 13, 14, 15, 16)) + ) + ); + assertThat(result.toParentAssert()).isSameAs(assertions); + assertThat(result.toRootAssert()).isSameAs(assertions.toRootAssert()); + assertThat(result.getActual()) + .hasSize(4) + .extracting(DbEntity::getId).contains(11L, 12L, 14L, 16L); + } + } + + @Nested + @DisplayName("haveNoStartingNodes") + class HaveNoStartingNodesTests extends BaseRelationshipsTests { + + HaveNoStartingNodesTests() { + super( + Models.relation().start(11), + Models.relation().start(12), + Models.relation().start(13), + Models.relation().start(14), + Models.relation().start(15), + Models.relation().start(16) + ); + } + + @Test + void should_fail() { + // GIVEN + final DbNode node1 = Models.node().id(11).labels("lbl", "lbl-1", "lbl-other-1").build(); + final DbNode node2 = Models.node().id(12).labels("lbl", "lbl-2", "lbl-other-2").build(); + final DbNode node3 = Models.node().id(13).labels("lbl", "lbl-3", "lbl-other-3").build(); + final DbNode node4 = Models.node().id(14).labels("lbl-other-4").build(); + final DbNode node5 = Models.node().id(15).labels("lbl-other-5").build(); + final DbNode node6 = Models.node().id(16).build(); + when(dataLoader.chain(any())).thenReturn(Loaders.nodes(node1, node2, node3, node4, node5, node6)); + + // WHEN + final Throwable throwable = catchThrowable(() -> this.assertions.haveNoStartingNodes("lbl", "lbl-4")); + + // THEN + verify(dataLoader).chain( + argQuery("MATCH (n) WHERE id(n) IN $ids RETURN n", + entry("ids", Arrays.asList(11, 12, 13, 14, 15, 16)) + ) + ); + assertThat(throwable) + .isInstanceOf(AssertionError.class) + .hasMessageContainingAll( + "Expecting query:", + "to return an empty list of nodes but got 4 nodes:" + ); + } + + @Test + void should_pass() { + // GIVEN + final DbNode node1 = Models.node().id(11).labels("lbl", "lbl-1", "lbl-other-1").build(); + final DbNode node2 = Models.node().id(12).labels("lbl", "lbl-2", "lbl-other-2").build(); + final DbNode node3 = Models.node().id(13).labels("lbl", "lbl-3", "lbl-other-3").build(); + final DbNode node4 = Models.node().id(14).labels("lbl-other-4").build(); + final DbNode node5 = Models.node().id(15).labels("lbl-other-5").build(); + final DbNode node6 = Models.node().id(16).labels("lbl-other-6").build(); + when(dataLoader.chain(any())).thenReturn(Loaders.nodes(node1, node2, node3, node4, node5, node6)); + + // WHEN + final DriverRelationshipsAssert result = this.assertions.haveNoStartingNodes("lbl-other", "lbl-4"); + + // THEN + verify(dataLoader).chain( + argQuery("MATCH (n) WHERE id(n) IN $ids RETURN n", + entry("ids", Arrays.asList(11, 12, 13, 14, 15, 16)) + ) + ); + assertThat(result).isSameAs(assertions); + } + + } + + @Nested + @DisplayName("haveNoEndingNodes") + class HaveNoEndingNodesTests extends BaseRelationshipsTests { + + HaveNoEndingNodesTests() { + super( + Models.relation().end(11), + Models.relation().end(12), + Models.relation().end(13), + Models.relation().end(14), + Models.relation().end(15), + Models.relation().end(16) + ); + } + + @Test + void should_fail() { + // GIVEN + final DbNode node1 = Models.node().id(11).labels("lbl", "lbl-1", "lbl-other-1").build(); + final DbNode node2 = Models.node().id(12).labels("lbl", "lbl-2", "lbl-other-2").build(); + final DbNode node3 = Models.node().id(13).labels("lbl", "lbl-3", "lbl-other-3").build(); + final DbNode node4 = Models.node().id(14).labels("lbl-other-4").build(); + final DbNode node5 = Models.node().id(15).labels("lbl-other-5").build(); + final DbNode node6 = Models.node().id(15).build(); + when(dataLoader.chain(any())).thenReturn(Loaders.nodes(node1, node2, node3, node4, node5, node6)); + + // WHEN + final Throwable throwable = catchThrowable(() -> this.assertions.haveNoEndingNodes("lbl", "lbl-4")); + + // THEN + verify(dataLoader).chain( + argQuery("MATCH (n) WHERE id(n) IN $ids RETURN n", + entry("ids", Arrays.asList(11, 12, 13, 14, 15, 16)) + ) + ); + assertThat(throwable) + .isInstanceOf(AssertionError.class) + .hasMessageContainingAll( + "Expecting query:", + "to return an empty list of nodes but got 4 nodes:" + ); + } + + @Test + void should_pass() { + // GIVEN + final DbNode node1 = Models.node().id(11).labels("lbl", "lbl-1", "lbl-other-1").build(); + final DbNode node2 = Models.node().id(12).labels("lbl", "lbl-2", "lbl-other-2").build(); + final DbNode node3 = Models.node().id(13).labels("lbl", "lbl-3", "lbl-other-3").build(); + final DbNode node4 = Models.node().id(14).labels("lbl-other-4").build(); + final DbNode node5 = Models.node().id(15).labels("lbl-other-5").build(); + final DbNode node6 = Models.node().id(15).labels("lbl-other-6").build(); + when(dataLoader.chain(any())).thenReturn(Loaders.nodes(node1, node2, node3, node4, node5, node6)); + + // WHEN + final DriverRelationshipsAssert result = this.assertions.haveNoEndingNodes("lbl-other", "lbl-4"); + + // THEN + verify(dataLoader).chain( + argQuery("MATCH (n) WHERE id(n) IN $ids RETURN n", + entry("ids", Arrays.asList(11, 12, 13, 14, 15, 16)) + ) + ); + assertThat(result).isSameAs(assertions); + } + + } + } diff --git a/src/test/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssertTests.java b/src/test/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssertTests.java new file mode 100644 index 0000000..942f48c --- /dev/null +++ b/src/test/java/org/assertj/neo4j/api/beta/ChildrenDriverNodeAssertTests.java @@ -0,0 +1,90 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2013-2020 the original author or authors. + */ +package org.assertj.neo4j.api.beta; + +import org.assertj.neo4j.api.beta.testing.Builders; +import org.assertj.neo4j.api.beta.type.DbNode; +import org.assertj.neo4j.api.beta.type.Models; +import org.assertj.neo4j.api.beta.type.loader.DataLoader; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.neo4j.api.beta.testing.Bases.ConcreteParentAssert; +import static org.assertj.neo4j.api.beta.testing.Bases.ConcreteRootAssert; +import static org.assertj.neo4j.api.beta.testing.Bases.ROOT_ASSERT; + +/** + * @author patouche - 22/02/2021 + */ +class ChildrenDriverNodeAssertTests { + + private static class BaseChildrenNodeTests { + private final DbNode.DbNodeBuilder[] builders; + private final DataLoader loader = Mockito.mock(DataLoader.class); + + protected ChildrenDriverNodeAssert assertions; + + public BaseChildrenNodeTests(DbNode.DbNodeBuilder... builders) { + this.builders = builders; + } + + @BeforeEach + void setUp() { + final List nodes = Arrays.stream(this.builders) + .map(DbNode.DbNodeBuilder::build) + .collect(Collectors.toList()); + this.assertions = new ChildrenDriverNodeAssert<>(nodes, loader, Builders.parent().build()); + } + + @AfterEach + void tearDown() { + Mockito.verifyNoMoreInteractions(loader); + } + } + + @Nested + class WithParentTests extends BaseChildrenNodeTests { + + public WithParentTests() { + super( + Models.node().id(1).labels("lbl-1"), + Models.node().id(2).labels("lbl-2") + ); + } + + @Test + void should_attach_to_parent() { + // GIVE? + final ConcreteParentAssert newParentAssert = Builders.parent().build(); + + // WHEN + final ChildrenDriverNodeAssert result = + this.assertions.withParent(newParentAssert); + + // THEN + assertThat(result).isNotSameAs(this.assertions); + assertThat(result.toParentAssert()).isSameAs(newParentAssert); + assertThat(result.toRootAssert()).isSameAs(ROOT_ASSERT); + + } + + } +} diff --git a/src/test/java/org/assertj/neo4j/api/beta/ChildrenListAssertTests.java b/src/test/java/org/assertj/neo4j/api/beta/ChildrenListAssertTests.java index c40ae3e..04a0121 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/ChildrenListAssertTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/ChildrenListAssertTests.java @@ -13,8 +13,8 @@ package org.assertj.neo4j.api.beta; import org.assertj.core.presentation.StandardRepresentation; +import org.assertj.neo4j.api.beta.testing.Builders; import org.assertj.neo4j.api.beta.testing.Samples; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -24,6 +24,9 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.neo4j.api.beta.testing.Bases.ConcreteParentAssert; +import static org.assertj.neo4j.api.beta.testing.Bases.ConcreteRootAssert; +import static org.assertj.neo4j.api.beta.testing.Bases.ROOT_ASSERT; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -33,15 +36,10 @@ */ class ChildrenListAssertTests { - private static class TestRootAssert { - } - private static class BaseChildrenListAssertTests { - protected ChildrenListAssert, TestRootAssert> assertions; + protected ChildrenListAssert assertions; protected final List actual; - protected final ParentAssert parentAssert = Mockito.mock(ParentAssert.class); - protected final TestRootAssert rootAssert = new TestRootAssert(); @SafeVarargs BaseChildrenListAssertTests(ACTUAL... elements) { @@ -50,17 +48,9 @@ private static class BaseChildrenListAssertTests { @BeforeEach void setUp() { - when(parentAssert.representation()).thenReturn(StandardRepresentation.STANDARD_REPRESENTATION); - when(parentAssert.toRootAssert()).thenReturn(rootAssert); - this.assertions = new ChildrenListAssert<>(this.actual, this.parentAssert); + this.assertions = new ChildrenListAssert<>(this.actual, Builders.parent().build()); } - @AfterEach - void tearDown() { - verify(parentAssert).representation(); - verify(parentAssert).toRootAssert(); - Mockito.verifyNoMoreInteractions(parentAssert); - } } @Nested @@ -73,12 +63,12 @@ class WithParentTests extends BaseChildrenListAssertTests { @Test void should_create_new_with_parent() { // GIVEN - final ParentAssert newParentAssert = Mockito.mock(ParentAssert.class); - when(newParentAssert.toRootAssert()).thenReturn(rootAssert); + final ConcreteParentAssert newParentAssert = Mockito.mock(ConcreteParentAssert.class); + when(newParentAssert.toRootAssert()).thenReturn(ROOT_ASSERT); when(newParentAssert.representation()).thenReturn(StandardRepresentation.STANDARD_REPRESENTATION); // WHEN - ChildrenListAssert, TestRootAssert> result = + ChildrenListAssert result = assertions.withParent(newParentAssert); // THEN diff --git a/src/test/java/org/assertj/neo4j/api/beta/DriverResultAssertTests.java b/src/test/java/org/assertj/neo4j/api/beta/DriverResultAssertTests.java index f42f135..55e69bd 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/DriverResultAssertTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/DriverResultAssertTests.java @@ -526,4 +526,53 @@ void should_return_a_children_relationship_assert() { } } + + @Nested + class AsNodeAssertTests extends BaseResultTests { + + public AsNodeAssertTests() { + super(SAMPLE_RECORDS_BUILDERS.toArray(new RecordBuilder[0])); + } + + @Test + void should_fail_when_column_not_found() { + // WHEN + final Throwable throwable = catchThrowable(() -> assertions.asNodeAssert("bad_column")); + + // THEN + assertThat(throwable) + .isInstanceOf(AssertionError.class) + .hasMessageContainingAll( + "Expecting ArrayList:", + "to contain:", + "but could not find the following element(s):" + ); + } + + @Test + void should_fail_when_column_is_not_a_relationship() { + // WHEN + final Throwable throwable = catchThrowable(() -> assertions.asNodeAssert("r")); + + // THEN + assertThat(throwable) + .isInstanceOf(AssertionError.class) + .hasMessageContainingAll( + "Expecting database objects:", + "to be of type:", + "but some database objects are from another type:" + ); + } + + @Test + void should_return_a_children_node_assert() { + // WHEN + final ChildrenDriverNodeAssert result = + assertions.asNodeAssert("n"); + + // THEN + assertThat(result.toParentAssert()).isSameAs(assertions); + } + } + } diff --git a/src/test/java/org/assertj/neo4j/api/beta/integrations/SampleNodesIntegrationTests.java b/src/test/java/org/assertj/neo4j/api/beta/integrations/SampleNodesIntegrationTests.java index 264e9b0..ed053ac 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/integrations/SampleNodesIntegrationTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/integrations/SampleNodesIntegrationTests.java @@ -47,7 +47,7 @@ public WithIdTests() { public void contains() { final Nodes nodes = Nodes.of(driver, "Language"); DriverAssertions.assertThat(nodes) - .contains(Models.node().id(6).label("Language").property("name", "Scala").build()); + .contains(Models.node().id(6).labels("Language").property("name", "Scala").build()); } } @@ -219,7 +219,7 @@ void ignoringIds() { final Nodes nodes = Nodes.of(driver, "Language"); DriverAssertions.assertThat(nodes) .usingNoEntityIdComparison() - .contains(Models.node().label("Language").property("name", "Scala").build()); + .contains(Models.node().labels("Language").property("name", "Scala").build()); } @Test diff --git a/src/test/java/org/assertj/neo4j/api/beta/testing/Bases.java b/src/test/java/org/assertj/neo4j/api/beta/testing/Bases.java new file mode 100644 index 0000000..77c9535 --- /dev/null +++ b/src/test/java/org/assertj/neo4j/api/beta/testing/Bases.java @@ -0,0 +1,57 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2013-2020 the original author or authors. + */ +package org.assertj.neo4j.api.beta.testing; + +import org.assertj.core.presentation.Representation; +import org.assertj.core.presentation.StandardRepresentation; +import org.assertj.neo4j.api.beta.ParentAssert; + +import java.util.Optional; + +/** + * @author patouche - 22/02/2021 + */ +public interface Bases { + + ConcreteRootAssert ROOT_ASSERT = new ConcreteRootAssert(); + + class ConcreteRootAssert { + + private ConcreteRootAssert() { + } + + } + + class ConcreteParentAssert implements ParentAssert { + + private final Representation representation; + private final ConcreteRootAssert rootAssert; + + public ConcreteParentAssert(final Representation representation, final ConcreteRootAssert rootAssert) { + this.representation = Optional.ofNullable(representation) + .orElse(StandardRepresentation.STANDARD_REPRESENTATION); + this.rootAssert = rootAssert; + } + + @Override + public Representation representation() { + return representation; + } + + @Override + public ConcreteRootAssert toRootAssert() { + return rootAssert; + } + + } +} diff --git a/src/test/java/org/assertj/neo4j/api/beta/testing/Builders.java b/src/test/java/org/assertj/neo4j/api/beta/testing/Builders.java index c9366ad..5b0d2f0 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/testing/Builders.java +++ b/src/test/java/org/assertj/neo4j/api/beta/testing/Builders.java @@ -12,6 +12,7 @@ */ package org.assertj.neo4j.api.beta.testing; +import org.assertj.neo4j.api.beta.testing.builders.ConcreteParentAssertBuilder; import org.assertj.neo4j.api.beta.testing.builders.NodeBuilder; import org.assertj.neo4j.api.beta.testing.builders.RecordBuilder; import org.assertj.neo4j.api.beta.testing.builders.RelationshipBuilder; @@ -37,7 +38,6 @@ static RelationshipBuilder relation(final String type) { return new RelationshipBuilder(type); } - static DbNode.DbNodeBuilder rebuild(DbNode node) { return Models.node() .id(node.getId()) @@ -54,4 +54,9 @@ static DbRelationship.DbRelationshipBuilder rebuild(DbRelationship relationship) .properties(DbObjectUtils.propertyObjects(relationship)); } + static ConcreteParentAssertBuilder parent() { + return new ConcreteParentAssertBuilder(); + } + + } diff --git a/src/test/java/org/assertj/neo4j/api/beta/testing/Loaders.java b/src/test/java/org/assertj/neo4j/api/beta/testing/Loaders.java index bcdaaa7..c424adb 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/testing/Loaders.java +++ b/src/test/java/org/assertj/neo4j/api/beta/testing/Loaders.java @@ -12,8 +12,11 @@ */ package org.assertj.neo4j.api.beta.testing; +import org.assertj.neo4j.api.beta.testing.builders.NodesLoaderBuilder; import org.assertj.neo4j.api.beta.testing.builders.RelationshipsLoaderBuilder; +import org.assertj.neo4j.api.beta.type.DbNode; import org.assertj.neo4j.api.beta.type.DbRelationship; +import org.assertj.neo4j.api.beta.type.loader.Nodes; import org.assertj.neo4j.api.beta.type.loader.Relationships; /** @@ -28,4 +31,12 @@ static RelationshipsLoaderBuilder relationships() { static Relationships relationships(DbRelationship... entities) { return relationships().entities(entities).build(); } + + static NodesLoaderBuilder nodes() { + return new NodesLoaderBuilder(); + } + + static Nodes nodes(DbNode ... entities) { + return nodes().entities(entities).build(); + } } diff --git a/src/test/java/org/assertj/neo4j/api/beta/testing/builders/ConcreteParentAssertBuilder.java b/src/test/java/org/assertj/neo4j/api/beta/testing/builders/ConcreteParentAssertBuilder.java new file mode 100644 index 0000000..27e5a47 --- /dev/null +++ b/src/test/java/org/assertj/neo4j/api/beta/testing/builders/ConcreteParentAssertBuilder.java @@ -0,0 +1,40 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2013-2020 the original author or authors. + */ +package org.assertj.neo4j.api.beta.testing.builders; + +import org.assertj.core.presentation.Representation; +import org.assertj.core.presentation.StandardRepresentation; +import org.assertj.neo4j.api.beta.testing.Bases; + +/** + * @author patouche - 22/02/2021 + */ +public class ConcreteParentAssertBuilder { + + private Representation representation = StandardRepresentation.STANDARD_REPRESENTATION; + private Bases.ConcreteRootAssert rootAssert = Bases.ROOT_ASSERT; + + public ConcreteParentAssertBuilder representation(Representation representation) { + this.representation = representation; + return this; + } + + public ConcreteParentAssertBuilder rootAssert(Bases.ConcreteRootAssert rootAssert) { + this.rootAssert = rootAssert; + return this; + } + + public Bases.ConcreteParentAssert build() { + return new Bases.ConcreteParentAssert(representation, rootAssert); + } +} diff --git a/src/test/java/org/assertj/neo4j/api/beta/testing/builders/NodesLoaderBuilder.java b/src/test/java/org/assertj/neo4j/api/beta/testing/builders/NodesLoaderBuilder.java new file mode 100644 index 0000000..150ea4b --- /dev/null +++ b/src/test/java/org/assertj/neo4j/api/beta/testing/builders/NodesLoaderBuilder.java @@ -0,0 +1,69 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2013-2020 the original author or authors. + */ +package org.assertj.neo4j.api.beta.testing.builders; + +import org.assertj.neo4j.api.beta.type.DbNode; +import org.assertj.neo4j.api.beta.type.DbRelationship; +import org.assertj.neo4j.api.beta.type.loader.DataLoader; +import org.assertj.neo4j.api.beta.type.loader.LoaderFactory; +import org.assertj.neo4j.api.beta.type.loader.Nodes; +import org.assertj.neo4j.api.beta.type.loader.Relationships; +import org.neo4j.driver.Query; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author Patrick Allain - 12/02/2021 + */ +public class NodesLoaderBuilder { + private DataLoader factoryResult; + private List entities = new ArrayList<>(); + private Query query; + + public NodesLoaderBuilder factoryResult(DataLoader factoryResult) { + this.factoryResult = factoryResult; + return this; + } + + public NodesLoaderBuilder entities(DbNode... entities) { + this.entities = Arrays.asList(entities); + return this; + } + + public NodesLoaderBuilder query(Query query) { + this.query = query; + return this; + } + + public Nodes build() { + return new Nodes() { + + @Override + public Query query() { + return query; + } + + @Override + public List load() { + return entities; + } + + @Override + public > D chain(final LoaderFactory factory) { + return (D) factory; + } + }; + } +} diff --git a/src/test/java/org/assertj/neo4j/api/beta/type/loader/NodesTests.java b/src/test/java/org/assertj/neo4j/api/beta/type/loader/NodesTests.java index 3449890..c333aeb 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/type/loader/NodesTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/type/loader/NodesTests.java @@ -82,8 +82,8 @@ void load_when_no_labels() { assertThat(dbNodes) .hasSize(2) .contains( - Models.node().id(0).label("Sample").property("prop-0", true).build(), - Models.node().id(1).label("Sample").property("prop-1", false).build() + Models.node().id(0).labels("Sample").property("prop-0", true).build(), + Models.node().id(1).labels("Sample").property("prop-1", false).build() ); assertThat(nodes.query()).isEqualTo(new Query("MATCH (n ) RETURN n")); diff --git a/src/test/java/org/assertj/neo4j/api/beta/util/DbObjectUtilsTests.java b/src/test/java/org/assertj/neo4j/api/beta/util/DbObjectUtilsTests.java index 837174a..fb3a165 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/util/DbObjectUtilsTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/util/DbObjectUtilsTests.java @@ -168,6 +168,29 @@ void should_return_the_start_node_ids() { } + @Nested + class ArrayStartNodeIdsTests { + + @Test + void should_return_the_start_node_ids() { + // GIVEN + final DbRelationship relationship1 = Models.relation().id(1).start(22).build(); + final DbRelationship relationship2 = Models.relation().id(2).start(29).build(); + final DbRelationship relationship3 = Models.relation().id(3).start(35).build(); + final DbRelationship relationship4 = Models.relation().id(4).start(42).build(); + final DbRelationship relationship5 = Models.relation().id(5).start(56).build(); + final DbRelationship relationship6 = Models.relation().id(6).start(42).build(); + final List relationships = Randomize + .listOf(relationship1, relationship2, relationship3, relationship4, relationship5, relationship6); + + // WHEN + final Long[] result = DbObjectUtils.arrayStartNodeIds(relationships); + + // THEN + assertThat(result).containsExactly(22L, 29L, 35L, 42L, 42L, 56L); + } + } + @Nested class EndNodeIdsTests { @@ -192,6 +215,30 @@ void should_return_the_end_node_ids() { } + @Nested + class ArrayEndNodeIdsTests { + + @Test + void should_return_the_end_node_ids() { + // GIVEN + final DbRelationship relationship1 = Models.relation().id(1).end(22).build(); + final DbRelationship relationship2 = Models.relation().id(2).end(29).build(); + final DbRelationship relationship3 = Models.relation().id(3).end(35).build(); + final DbRelationship relationship4 = Models.relation().id(4).end(42).build(); + final DbRelationship relationship5 = Models.relation().id(5).end(56).build(); + final DbRelationship relationship6 = Models.relation().id(6).end(42).build(); + final List relationships = Randomize + .listOf(relationship1, relationship2, relationship3, relationship4, relationship5, relationship6); + + // WHEN + final Long[] result = DbObjectUtils.arrayEndNodeIds(relationships); + + // THEN + assertThat(result).containsExactly(22L, 29L, 35L, 42L, 42L, 56L); + } + + } + @Nested @ExtendWith(SoftAssertionsExtension.class) class PropertyListTests { diff --git a/src/test/java/org/assertj/neo4j/api/beta/util/NodeComparisonStrategyTests.java b/src/test/java/org/assertj/neo4j/api/beta/util/NodeComparisonStrategyTests.java index ddc4e98..d7c3477 100644 --- a/src/test/java/org/assertj/neo4j/api/beta/util/NodeComparisonStrategyTests.java +++ b/src/test/java/org/assertj/neo4j/api/beta/util/NodeComparisonStrategyTests.java @@ -68,7 +68,7 @@ void should_return_true_when_ignore_ids() { @Test void should_return_false_when_ignore_ids() { // GIVEN - final DbNode other = Builders.rebuild(SAMPLE_NODE).id(42).label("LBL_4").build(); + final DbNode other = Builders.rebuild(SAMPLE_NODE).id(42).labels("LBL_4").build(); final NodeComparisonStrategy strategy = builder().ignoreId(true).build(); // WHEN diff --git a/src/test/resources/samples/movies.cypher b/src/test/resources/samples/movies.cypher new file mode 100644 index 0000000..dda63b4 --- /dev/null +++ b/src/test/resources/samples/movies.cypher @@ -0,0 +1,507 @@ +CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'}) +CREATE (Keanu:Person {name:'Keanu Reeves', born:1964}) +CREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967}) +CREATE (Laurence:Person {name:'Laurence Fishburne', born:1961}) +CREATE (Hugo:Person {name:'Hugo Weaving', born:1960}) +CREATE (LillyW:Person {name:'Lilly Wachowski', born:1967}) +CREATE (LanaW:Person {name:'Lana Wachowski', born:1965}) +CREATE (JoelS:Person {name:'Joel Silver', born:1952}) +CREATE + (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix), + (Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrix), + (Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrix), + (Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrix), + (LillyW)-[:DIRECTED]->(TheMatrix), + (LanaW)-[:DIRECTED]->(TheMatrix), + (JoelS)-[:PRODUCED]->(TheMatrix) + +CREATE (Emil:Person {name:"Emil Eifrem", born:1978}) +CREATE (Emil)-[:ACTED_IN {roles:["Emil"]}]->(TheMatrix) + +CREATE (TheMatrixReloaded:Movie {title:'The Matrix Reloaded', released:2003, tagline:'Free your mind'}) +CREATE + (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixReloaded), + (Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixReloaded), + (Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixReloaded), + (Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixReloaded), + (LillyW)-[:DIRECTED]->(TheMatrixReloaded), + (LanaW)-[:DIRECTED]->(TheMatrixReloaded), + (JoelS)-[:PRODUCED]->(TheMatrixReloaded) + +CREATE (TheMatrixRevolutions:Movie {title:'The Matrix Revolutions', released:2003, tagline:'Everything that has a beginning has an end'}) +CREATE + (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixRevolutions), + (Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixRevolutions), + (Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixRevolutions), + (Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixRevolutions), + (LillyW)-[:DIRECTED]->(TheMatrixRevolutions), + (LanaW)-[:DIRECTED]->(TheMatrixRevolutions), + (JoelS)-[:PRODUCED]->(TheMatrixRevolutions) + +CREATE (TheDevilsAdvocate:Movie {title:"The Devil's Advocate", released:1997, tagline:'Evil has its winning ways'}) +CREATE (Charlize:Person {name:'Charlize Theron', born:1975}) +CREATE (Al:Person {name:'Al Pacino', born:1940}) +CREATE (Taylor:Person {name:'Taylor Hackford', born:1944}) +CREATE + (Keanu)-[:ACTED_IN {roles:['Kevin Lomax']}]->(TheDevilsAdvocate), + (Charlize)-[:ACTED_IN {roles:['Mary Ann Lomax']}]->(TheDevilsAdvocate), + (Al)-[:ACTED_IN {roles:['John Milton']}]->(TheDevilsAdvocate), + (Taylor)-[:DIRECTED]->(TheDevilsAdvocate) + +CREATE (AFewGoodMen:Movie {title:"A Few Good Men", released:1992, tagline:"In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth."}) +CREATE (TomC:Person {name:'Tom Cruise', born:1962}) +CREATE (JackN:Person {name:'Jack Nicholson', born:1937}) +CREATE (DemiM:Person {name:'Demi Moore', born:1962}) +CREATE (KevinB:Person {name:'Kevin Bacon', born:1958}) +CREATE (KieferS:Person {name:'Kiefer Sutherland', born:1966}) +CREATE (NoahW:Person {name:'Noah Wyle', born:1971}) +CREATE (CubaG:Person {name:'Cuba Gooding Jr.', born:1968}) +CREATE (KevinP:Person {name:'Kevin Pollak', born:1957}) +CREATE (JTW:Person {name:'J.T. Walsh', born:1943}) +CREATE (JamesM:Person {name:'James Marshall', born:1967}) +CREATE (ChristopherG:Person {name:'Christopher Guest', born:1948}) +CREATE (RobR:Person {name:'Rob Reiner', born:1947}) +CREATE (AaronS:Person {name:'Aaron Sorkin', born:1961}) +CREATE + (TomC)-[:ACTED_IN {roles:['Lt. Daniel Kaffee']}]->(AFewGoodMen), + (JackN)-[:ACTED_IN {roles:['Col. Nathan R. Jessup']}]->(AFewGoodMen), + (DemiM)-[:ACTED_IN {roles:['Lt. Cdr. JoAnne Galloway']}]->(AFewGoodMen), + (KevinB)-[:ACTED_IN {roles:['Capt. Jack Ross']}]->(AFewGoodMen), + (KieferS)-[:ACTED_IN {roles:['Lt. Jonathan Kendrick']}]->(AFewGoodMen), + (NoahW)-[:ACTED_IN {roles:['Cpl. Jeffrey Barnes']}]->(AFewGoodMen), + (CubaG)-[:ACTED_IN {roles:['Cpl. Carl Hammaker']}]->(AFewGoodMen), + (KevinP)-[:ACTED_IN {roles:['Lt. Sam Weinberg']}]->(AFewGoodMen), + (JTW)-[:ACTED_IN {roles:['Lt. Col. Matthew Andrew Markinson']}]->(AFewGoodMen), + (JamesM)-[:ACTED_IN {roles:['Pfc. Louden Downey']}]->(AFewGoodMen), + (ChristopherG)-[:ACTED_IN {roles:['Dr. Stone']}]->(AFewGoodMen), + (AaronS)-[:ACTED_IN {roles:['Man in Bar']}]->(AFewGoodMen), + (RobR)-[:DIRECTED]->(AFewGoodMen), + (AaronS)-[:WROTE]->(AFewGoodMen) + +CREATE (TopGun:Movie {title:"Top Gun", released:1986, tagline:'I feel the need, the need for speed.'}) +CREATE (KellyM:Person {name:'Kelly McGillis', born:1957}) +CREATE (ValK:Person {name:'Val Kilmer', born:1959}) +CREATE (AnthonyE:Person {name:'Anthony Edwards', born:1962}) +CREATE (TomS:Person {name:'Tom Skerritt', born:1933}) +CREATE (MegR:Person {name:'Meg Ryan', born:1961}) +CREATE (TonyS:Person {name:'Tony Scott', born:1944}) +CREATE (JimC:Person {name:'Jim Cash', born:1941}) +CREATE + (TomC)-[:ACTED_IN {roles:['Maverick']}]->(TopGun), + (KellyM)-[:ACTED_IN {roles:['Charlie']}]->(TopGun), + (ValK)-[:ACTED_IN {roles:['Iceman']}]->(TopGun), + (AnthonyE)-[:ACTED_IN {roles:['Goose']}]->(TopGun), + (TomS)-[:ACTED_IN {roles:['Viper']}]->(TopGun), + (MegR)-[:ACTED_IN {roles:['Carole']}]->(TopGun), + (TonyS)-[:DIRECTED]->(TopGun), + (JimC)-[:WROTE]->(TopGun) + +CREATE (JerryMaguire:Movie {title:'Jerry Maguire', released:2000, tagline:'The rest of his life begins now.'}) +CREATE (ReneeZ:Person {name:'Renee Zellweger', born:1969}) +CREATE (KellyP:Person {name:'Kelly Preston', born:1962}) +CREATE (JerryO:Person {name:"Jerry O'Connell", born:1974}) +CREATE (JayM:Person {name:'Jay Mohr', born:1970}) +CREATE (BonnieH:Person {name:'Bonnie Hunt', born:1961}) +CREATE (ReginaK:Person {name:'Regina King', born:1971}) +CREATE (JonathanL:Person {name:'Jonathan Lipnicki', born:1996}) +CREATE (CameronC:Person {name:'Cameron Crowe', born:1957}) +CREATE + (TomC)-[:ACTED_IN {roles:['Jerry Maguire']}]->(JerryMaguire), + (CubaG)-[:ACTED_IN {roles:['Rod Tidwell']}]->(JerryMaguire), + (ReneeZ)-[:ACTED_IN {roles:['Dorothy Boyd']}]->(JerryMaguire), + (KellyP)-[:ACTED_IN {roles:['Avery Bishop']}]->(JerryMaguire), + (JerryO)-[:ACTED_IN {roles:['Frank Cushman']}]->(JerryMaguire), + (JayM)-[:ACTED_IN {roles:['Bob Sugar']}]->(JerryMaguire), + (BonnieH)-[:ACTED_IN {roles:['Laurel Boyd']}]->(JerryMaguire), + (ReginaK)-[:ACTED_IN {roles:['Marcee Tidwell']}]->(JerryMaguire), + (JonathanL)-[:ACTED_IN {roles:['Ray Boyd']}]->(JerryMaguire), + (CameronC)-[:DIRECTED]->(JerryMaguire), + (CameronC)-[:PRODUCED]->(JerryMaguire), + (CameronC)-[:WROTE]->(JerryMaguire) + +CREATE (StandByMe:Movie {title:"Stand By Me", released:1986, tagline:"For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of."}) +CREATE (RiverP:Person {name:'River Phoenix', born:1970}) +CREATE (CoreyF:Person {name:'Corey Feldman', born:1971}) +CREATE (WilW:Person {name:'Wil Wheaton', born:1972}) +CREATE (JohnC:Person {name:'John Cusack', born:1966}) +CREATE (MarshallB:Person {name:'Marshall Bell', born:1942}) +CREATE + (WilW)-[:ACTED_IN {roles:['Gordie Lachance']}]->(StandByMe), + (RiverP)-[:ACTED_IN {roles:['Chris Chambers']}]->(StandByMe), + (JerryO)-[:ACTED_IN {roles:['Vern Tessio']}]->(StandByMe), + (CoreyF)-[:ACTED_IN {roles:['Teddy Duchamp']}]->(StandByMe), + (JohnC)-[:ACTED_IN {roles:['Denny Lachance']}]->(StandByMe), + (KieferS)-[:ACTED_IN {roles:['Ace Merrill']}]->(StandByMe), + (MarshallB)-[:ACTED_IN {roles:['Mr. Lachance']}]->(StandByMe), + (RobR)-[:DIRECTED]->(StandByMe) + +CREATE (AsGoodAsItGets:Movie {title:'As Good as It Gets', released:1997, tagline:'A comedy from the heart that goes for the throat.'}) +CREATE (HelenH:Person {name:'Helen Hunt', born:1963}) +CREATE (GregK:Person {name:'Greg Kinnear', born:1963}) +CREATE (JamesB:Person {name:'James L. Brooks', born:1940}) +CREATE + (JackN)-[:ACTED_IN {roles:['Melvin Udall']}]->(AsGoodAsItGets), + (HelenH)-[:ACTED_IN {roles:['Carol Connelly']}]->(AsGoodAsItGets), + (GregK)-[:ACTED_IN {roles:['Simon Bishop']}]->(AsGoodAsItGets), + (CubaG)-[:ACTED_IN {roles:['Frank Sachs']}]->(AsGoodAsItGets), + (JamesB)-[:DIRECTED]->(AsGoodAsItGets) + +CREATE (WhatDreamsMayCome:Movie {title:'What Dreams May Come', released:1998, tagline:'After life there is more. The end is just the beginning.'}) +CREATE (AnnabellaS:Person {name:'Annabella Sciorra', born:1960}) +CREATE (MaxS:Person {name:'Max von Sydow', born:1929}) +CREATE (WernerH:Person {name:'Werner Herzog', born:1942}) +CREATE (Robin:Person {name:'Robin Williams', born:1951}) +CREATE (VincentW:Person {name:'Vincent Ward', born:1956}) +CREATE + (Robin)-[:ACTED_IN {roles:['Chris Nielsen']}]->(WhatDreamsMayCome), + (CubaG)-[:ACTED_IN {roles:['Albert Lewis']}]->(WhatDreamsMayCome), + (AnnabellaS)-[:ACTED_IN {roles:['Annie Collins-Nielsen']}]->(WhatDreamsMayCome), + (MaxS)-[:ACTED_IN {roles:['The Tracker']}]->(WhatDreamsMayCome), + (WernerH)-[:ACTED_IN {roles:['The Face']}]->(WhatDreamsMayCome), + (VincentW)-[:DIRECTED]->(WhatDreamsMayCome) + +CREATE (SnowFallingonCedars:Movie {title:'Snow Falling on Cedars', released:1999, tagline:'First loves last. Forever.'}) +CREATE (EthanH:Person {name:'Ethan Hawke', born:1970}) +CREATE (RickY:Person {name:'Rick Yune', born:1971}) +CREATE (JamesC:Person {name:'James Cromwell', born:1940}) +CREATE (ScottH:Person {name:'Scott Hicks', born:1953}) +CREATE + (EthanH)-[:ACTED_IN {roles:['Ishmael Chambers']}]->(SnowFallingonCedars), + (RickY)-[:ACTED_IN {roles:['Kazuo Miyamoto']}]->(SnowFallingonCedars), + (MaxS)-[:ACTED_IN {roles:['Nels Gudmundsson']}]->(SnowFallingonCedars), + (JamesC)-[:ACTED_IN {roles:['Judge Fielding']}]->(SnowFallingonCedars), + (ScottH)-[:DIRECTED]->(SnowFallingonCedars) + +CREATE (YouveGotMail:Movie {title:"You've Got Mail", released:1998, tagline:'At odds in life... in love on-line.'}) +CREATE (ParkerP:Person {name:'Parker Posey', born:1968}) +CREATE (DaveC:Person {name:'Dave Chappelle', born:1973}) +CREATE (SteveZ:Person {name:'Steve Zahn', born:1967}) +CREATE (TomH:Person {name:'Tom Hanks', born:1956}) +CREATE (NoraE:Person {name:'Nora Ephron', born:1941}) +CREATE + (TomH)-[:ACTED_IN {roles:['Joe Fox']}]->(YouveGotMail), + (MegR)-[:ACTED_IN {roles:['Kathleen Kelly']}]->(YouveGotMail), + (GregK)-[:ACTED_IN {roles:['Frank Navasky']}]->(YouveGotMail), + (ParkerP)-[:ACTED_IN {roles:['Patricia Eden']}]->(YouveGotMail), + (DaveC)-[:ACTED_IN {roles:['Kevin Jackson']}]->(YouveGotMail), + (SteveZ)-[:ACTED_IN {roles:['George Pappas']}]->(YouveGotMail), + (NoraE)-[:DIRECTED]->(YouveGotMail) + +CREATE (SleeplessInSeattle:Movie {title:'Sleepless in Seattle', released:1993, tagline:'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?'}) +CREATE (RitaW:Person {name:'Rita Wilson', born:1956}) +CREATE (BillPull:Person {name:'Bill Pullman', born:1953}) +CREATE (VictorG:Person {name:'Victor Garber', born:1949}) +CREATE (RosieO:Person {name:"Rosie O'Donnell", born:1962}) +CREATE + (TomH)-[:ACTED_IN {roles:['Sam Baldwin']}]->(SleeplessInSeattle), + (MegR)-[:ACTED_IN {roles:['Annie Reed']}]->(SleeplessInSeattle), + (RitaW)-[:ACTED_IN {roles:['Suzy']}]->(SleeplessInSeattle), + (BillPull)-[:ACTED_IN {roles:['Walter']}]->(SleeplessInSeattle), + (VictorG)-[:ACTED_IN {roles:['Greg']}]->(SleeplessInSeattle), + (RosieO)-[:ACTED_IN {roles:['Becky']}]->(SleeplessInSeattle), + (NoraE)-[:DIRECTED]->(SleeplessInSeattle) + +CREATE (JoeVersustheVolcano:Movie {title:'Joe Versus the Volcano', released:1990, tagline:'A story of love, lava and burning desire.'}) +CREATE (JohnS:Person {name:'John Patrick Stanley', born:1950}) +CREATE (Nathan:Person {name:'Nathan Lane', born:1956}) +CREATE + (TomH)-[:ACTED_IN {roles:['Joe Banks']}]->(JoeVersustheVolcano), + (MegR)-[:ACTED_IN {roles:['DeDe', 'Angelica Graynamore', 'Patricia Graynamore']}]->(JoeVersustheVolcano), + (Nathan)-[:ACTED_IN {roles:['Baw']}]->(JoeVersustheVolcano), + (JohnS)-[:DIRECTED]->(JoeVersustheVolcano) + +CREATE (WhenHarryMetSally:Movie {title:'When Harry Met Sally', released:1998, tagline:'Can two friends sleep together and still love each other in the morning?'}) +CREATE (BillyC:Person {name:'Billy Crystal', born:1948}) +CREATE (CarrieF:Person {name:'Carrie Fisher', born:1956}) +CREATE (BrunoK:Person {name:'Bruno Kirby', born:1949}) +CREATE + (BillyC)-[:ACTED_IN {roles:['Harry Burns']}]->(WhenHarryMetSally), + (MegR)-[:ACTED_IN {roles:['Sally Albright']}]->(WhenHarryMetSally), + (CarrieF)-[:ACTED_IN {roles:['Marie']}]->(WhenHarryMetSally), + (BrunoK)-[:ACTED_IN {roles:['Jess']}]->(WhenHarryMetSally), + (RobR)-[:DIRECTED]->(WhenHarryMetSally), + (RobR)-[:PRODUCED]->(WhenHarryMetSally), + (NoraE)-[:PRODUCED]->(WhenHarryMetSally), + (NoraE)-[:WROTE]->(WhenHarryMetSally) + +CREATE (ThatThingYouDo:Movie {title:'That Thing You Do', released:1996, tagline:'In every life there comes a time when that thing you dream becomes that thing you do'}) +CREATE (LivT:Person {name:'Liv Tyler', born:1977}) +CREATE + (TomH)-[:ACTED_IN {roles:['Mr. White']}]->(ThatThingYouDo), + (LivT)-[:ACTED_IN {roles:['Faye Dolan']}]->(ThatThingYouDo), + (Charlize)-[:ACTED_IN {roles:['Tina']}]->(ThatThingYouDo), + (TomH)-[:DIRECTED]->(ThatThingYouDo) + +CREATE (TheReplacements:Movie {title:'The Replacements', released:2000, tagline:'Pain heals, Chicks dig scars... Glory lasts forever'}) +CREATE (Brooke:Person {name:'Brooke Langton', born:1970}) +CREATE (Gene:Person {name:'Gene Hackman', born:1930}) +CREATE (Orlando:Person {name:'Orlando Jones', born:1968}) +CREATE (Howard:Person {name:'Howard Deutch', born:1950}) +CREATE + (Keanu)-[:ACTED_IN {roles:['Shane Falco']}]->(TheReplacements), + (Brooke)-[:ACTED_IN {roles:['Annabelle Farrell']}]->(TheReplacements), + (Gene)-[:ACTED_IN {roles:['Jimmy McGinty']}]->(TheReplacements), + (Orlando)-[:ACTED_IN {roles:['Clifford Franklin']}]->(TheReplacements), + (Howard)-[:DIRECTED]->(TheReplacements) + +CREATE (RescueDawn:Movie {title:'RescueDawn', released:2006, tagline:"Based on the extraordinary true story of one man's fight for freedom"}) +CREATE (ChristianB:Person {name:'Christian Bale', born:1974}) +CREATE (ZachG:Person {name:'Zach Grenier', born:1954}) +CREATE + (MarshallB)-[:ACTED_IN {roles:['Admiral']}]->(RescueDawn), + (ChristianB)-[:ACTED_IN {roles:['Dieter Dengler']}]->(RescueDawn), + (ZachG)-[:ACTED_IN {roles:['Squad Leader']}]->(RescueDawn), + (SteveZ)-[:ACTED_IN {roles:['Duane']}]->(RescueDawn), + (WernerH)-[:DIRECTED]->(RescueDawn) + +CREATE (TheBirdcage:Movie {title:'The Birdcage', released:1996, tagline:'Come as you are'}) +CREATE (MikeN:Person {name:'Mike Nichols', born:1931}) +CREATE + (Robin)-[:ACTED_IN {roles:['Armand Goldman']}]->(TheBirdcage), + (Nathan)-[:ACTED_IN {roles:['Albert Goldman']}]->(TheBirdcage), + (Gene)-[:ACTED_IN {roles:['Sen. Kevin Keeley']}]->(TheBirdcage), + (MikeN)-[:DIRECTED]->(TheBirdcage) + +CREATE (Unforgiven:Movie {title:'Unforgiven', released:1992, tagline:"It's a hell of a thing, killing a man"}) +CREATE (RichardH:Person {name:'Richard Harris', born:1930}) +CREATE (ClintE:Person {name:'Clint Eastwood', born:1930}) +CREATE + (RichardH)-[:ACTED_IN {roles:['English Bob']}]->(Unforgiven), + (ClintE)-[:ACTED_IN {roles:['Bill Munny']}]->(Unforgiven), + (Gene)-[:ACTED_IN {roles:['Little Bill Daggett']}]->(Unforgiven), + (ClintE)-[:DIRECTED]->(Unforgiven) + +CREATE (JohnnyMnemonic:Movie {title:'Johnny Mnemonic', released:1995, tagline:'The hottest data on earth. In the coolest head in town'}) +CREATE (Takeshi:Person {name:'Takeshi Kitano', born:1947}) +CREATE (Dina:Person {name:'Dina Meyer', born:1968}) +CREATE (IceT:Person {name:'Ice-T', born:1958}) +CREATE (RobertL:Person {name:'Robert Longo', born:1953}) +CREATE + (Keanu)-[:ACTED_IN {roles:['Johnny Mnemonic']}]->(JohnnyMnemonic), + (Takeshi)-[:ACTED_IN {roles:['Takahashi']}]->(JohnnyMnemonic), + (Dina)-[:ACTED_IN {roles:['Jane']}]->(JohnnyMnemonic), + (IceT)-[:ACTED_IN {roles:['J-Bone']}]->(JohnnyMnemonic), + (RobertL)-[:DIRECTED]->(JohnnyMnemonic) + +CREATE (CloudAtlas:Movie {title:'Cloud Atlas', released:2012, tagline:'Everything is connected'}) +CREATE (HalleB:Person {name:'Halle Berry', born:1966}) +CREATE (JimB:Person {name:'Jim Broadbent', born:1949}) +CREATE (TomT:Person {name:'Tom Tykwer', born:1965}) +CREATE (DavidMitchell:Person {name:'David Mitchell', born:1969}) +CREATE (StefanArndt:Person {name:'Stefan Arndt', born:1961}) +CREATE + (TomH)-[:ACTED_IN {roles:['Zachry', 'Dr. Henry Goose', 'Isaac Sachs', 'Dermot Hoggins']}]->(CloudAtlas), + (Hugo)-[:ACTED_IN {roles:['Bill Smoke', 'Haskell Moore', 'Tadeusz Kesselring', 'Nurse Noakes', 'Boardman Mephi', 'Old Georgie']}]->(CloudAtlas), + (HalleB)-[:ACTED_IN {roles:['Luisa Rey', 'Jocasta Ayrs', 'Ovid', 'Meronym']}]->(CloudAtlas), + (JimB)-[:ACTED_IN {roles:['Vyvyan Ayrs', 'Captain Molyneux', 'Timothy Cavendish']}]->(CloudAtlas), + (TomT)-[:DIRECTED]->(CloudAtlas), + (LillyW)-[:DIRECTED]->(CloudAtlas), + (LanaW)-[:DIRECTED]->(CloudAtlas), + (DavidMitchell)-[:WROTE]->(CloudAtlas), + (StefanArndt)-[:PRODUCED]->(CloudAtlas) + +CREATE (TheDaVinciCode:Movie {title:'The Da Vinci Code', released:2006, tagline:'Break The Codes'}) +CREATE (IanM:Person {name:'Ian McKellen', born:1939}) +CREATE (AudreyT:Person {name:'Audrey Tautou', born:1976}) +CREATE (PaulB:Person {name:'Paul Bettany', born:1971}) +CREATE (RonH:Person {name:'Ron Howard', born:1954}) +CREATE + (TomH)-[:ACTED_IN {roles:['Dr. Robert Langdon']}]->(TheDaVinciCode), + (IanM)-[:ACTED_IN {roles:['Sir Leight Teabing']}]->(TheDaVinciCode), + (AudreyT)-[:ACTED_IN {roles:['Sophie Neveu']}]->(TheDaVinciCode), + (PaulB)-[:ACTED_IN {roles:['Silas']}]->(TheDaVinciCode), + (RonH)-[:DIRECTED]->(TheDaVinciCode) + +CREATE (VforVendetta:Movie {title:'V for Vendetta', released:2006, tagline:'Freedom! Forever!'}) +CREATE (NatalieP:Person {name:'Natalie Portman', born:1981}) +CREATE (StephenR:Person {name:'Stephen Rea', born:1946}) +CREATE (JohnH:Person {name:'John Hurt', born:1940}) +CREATE (BenM:Person {name: 'Ben Miles', born:1967}) +CREATE + (Hugo)-[:ACTED_IN {roles:['V']}]->(VforVendetta), + (NatalieP)-[:ACTED_IN {roles:['Evey Hammond']}]->(VforVendetta), + (StephenR)-[:ACTED_IN {roles:['Eric Finch']}]->(VforVendetta), + (JohnH)-[:ACTED_IN {roles:['High Chancellor Adam Sutler']}]->(VforVendetta), + (BenM)-[:ACTED_IN {roles:['Dascomb']}]->(VforVendetta), + (JamesM)-[:DIRECTED]->(VforVendetta), + (LillyW)-[:PRODUCED]->(VforVendetta), + (LanaW)-[:PRODUCED]->(VforVendetta), + (JoelS)-[:PRODUCED]->(VforVendetta), + (LillyW)-[:WROTE]->(VforVendetta), + (LanaW)-[:WROTE]->(VforVendetta) + +CREATE (SpeedRacer:Movie {title:'Speed Racer', released:2008, tagline:'Speed has no limits'}) +CREATE (EmileH:Person {name:'Emile Hirsch', born:1985}) +CREATE (JohnG:Person {name:'John Goodman', born:1960}) +CREATE (SusanS:Person {name:'Susan Sarandon', born:1946}) +CREATE (MatthewF:Person {name:'Matthew Fox', born:1966}) +CREATE (ChristinaR:Person {name:'Christina Ricci', born:1980}) +CREATE (Rain:Person {name:'Rain', born:1982}) +CREATE + (EmileH)-[:ACTED_IN {roles:['Speed Racer']}]->(SpeedRacer), + (JohnG)-[:ACTED_IN {roles:['Pops']}]->(SpeedRacer), + (SusanS)-[:ACTED_IN {roles:['Mom']}]->(SpeedRacer), + (MatthewF)-[:ACTED_IN {roles:['Racer X']}]->(SpeedRacer), + (ChristinaR)-[:ACTED_IN {roles:['Trixie']}]->(SpeedRacer), + (Rain)-[:ACTED_IN {roles:['Taejo Togokahn']}]->(SpeedRacer), + (BenM)-[:ACTED_IN {roles:['Cass Jones']}]->(SpeedRacer), + (LillyW)-[:DIRECTED]->(SpeedRacer), + (LanaW)-[:DIRECTED]->(SpeedRacer), + (LillyW)-[:WROTE]->(SpeedRacer), + (LanaW)-[:WROTE]->(SpeedRacer), + (JoelS)-[:PRODUCED]->(SpeedRacer) + +CREATE (NinjaAssassin:Movie {title:'Ninja Assassin', released:2009, tagline:'Prepare to enter a secret world of assassins'}) +CREATE (NaomieH:Person {name:'Naomie Harris'}) +CREATE + (Rain)-[:ACTED_IN {roles:['Raizo']}]->(NinjaAssassin), + (NaomieH)-[:ACTED_IN {roles:['Mika Coretti']}]->(NinjaAssassin), + (RickY)-[:ACTED_IN {roles:['Takeshi']}]->(NinjaAssassin), + (BenM)-[:ACTED_IN {roles:['Ryan Maslow']}]->(NinjaAssassin), + (JamesM)-[:DIRECTED]->(NinjaAssassin), + (LillyW)-[:PRODUCED]->(NinjaAssassin), + (LanaW)-[:PRODUCED]->(NinjaAssassin), + (JoelS)-[:PRODUCED]->(NinjaAssassin) + +CREATE (TheGreenMile:Movie {title:'The Green Mile', released:1999, tagline:"Walk a mile you'll never forget."}) +CREATE (MichaelD:Person {name:'Michael Clarke Duncan', born:1957}) +CREATE (DavidM:Person {name:'David Morse', born:1953}) +CREATE (SamR:Person {name:'Sam Rockwell', born:1968}) +CREATE (GaryS:Person {name:'Gary Sinise', born:1955}) +CREATE (PatriciaC:Person {name:'Patricia Clarkson', born:1959}) +CREATE (FrankD:Person {name:'Frank Darabont', born:1959}) +CREATE + (TomH)-[:ACTED_IN {roles:['Paul Edgecomb']}]->(TheGreenMile), + (MichaelD)-[:ACTED_IN {roles:['John Coffey']}]->(TheGreenMile), + (DavidM)-[:ACTED_IN {roles:['Brutus "Brutal" Howell']}]->(TheGreenMile), + (BonnieH)-[:ACTED_IN {roles:['Jan Edgecomb']}]->(TheGreenMile), + (JamesC)-[:ACTED_IN {roles:['Warden Hal Moores']}]->(TheGreenMile), + (SamR)-[:ACTED_IN {roles:['"Wild Bill" Wharton']}]->(TheGreenMile), + (GaryS)-[:ACTED_IN {roles:['Burt Hammersmith']}]->(TheGreenMile), + (PatriciaC)-[:ACTED_IN {roles:['Melinda Moores']}]->(TheGreenMile), + (FrankD)-[:DIRECTED]->(TheGreenMile) + +CREATE (FrostNixon:Movie {title:'Frost/Nixon', released:2008, tagline:'400 million people were waiting for the truth.'}) +CREATE (FrankL:Person {name:'Frank Langella', born:1938}) +CREATE (MichaelS:Person {name:'Michael Sheen', born:1969}) +CREATE (OliverP:Person {name:'Oliver Platt', born:1960}) +CREATE + (FrankL)-[:ACTED_IN {roles:['Richard Nixon']}]->(FrostNixon), + (MichaelS)-[:ACTED_IN {roles:['David Frost']}]->(FrostNixon), + (KevinB)-[:ACTED_IN {roles:['Jack Brennan']}]->(FrostNixon), + (OliverP)-[:ACTED_IN {roles:['Bob Zelnick']}]->(FrostNixon), + (SamR)-[:ACTED_IN {roles:['James Reston, Jr.']}]->(FrostNixon), + (RonH)-[:DIRECTED]->(FrostNixon) + +CREATE (Hoffa:Movie {title:'Hoffa', released:1992, tagline:"He didn't want law. He wanted justice."}) +CREATE (DannyD:Person {name:'Danny DeVito', born:1944}) +CREATE (JohnR:Person {name:'John C. Reilly', born:1965}) +CREATE + (JackN)-[:ACTED_IN {roles:['Hoffa']}]->(Hoffa), + (DannyD)-[:ACTED_IN {roles:['Robert "Bobby" Ciaro']}]->(Hoffa), + (JTW)-[:ACTED_IN {roles:['Frank Fitzsimmons']}]->(Hoffa), + (JohnR)-[:ACTED_IN {roles:['Peter "Pete" Connelly']}]->(Hoffa), + (DannyD)-[:DIRECTED]->(Hoffa) + +CREATE (Apollo13:Movie {title:'Apollo 13', released:1995, tagline:'Houston, we have a problem.'}) +CREATE (EdH:Person {name:'Ed Harris', born:1950}) +CREATE (BillPax:Person {name:'Bill Paxton', born:1955}) +CREATE + (TomH)-[:ACTED_IN {roles:['Jim Lovell']}]->(Apollo13), + (KevinB)-[:ACTED_IN {roles:['Jack Swigert']}]->(Apollo13), + (EdH)-[:ACTED_IN {roles:['Gene Kranz']}]->(Apollo13), + (BillPax)-[:ACTED_IN {roles:['Fred Haise']}]->(Apollo13), + (GaryS)-[:ACTED_IN {roles:['Ken Mattingly']}]->(Apollo13), + (RonH)-[:DIRECTED]->(Apollo13) + +CREATE (Twister:Movie {title:'Twister', released:1996, tagline:"Don't Breathe. Don't Look Back."}) +CREATE (PhilipH:Person {name:'Philip Seymour Hoffman', born:1967}) +CREATE (JanB:Person {name:'Jan de Bont', born:1943}) +CREATE + (BillPax)-[:ACTED_IN {roles:['Bill Harding']}]->(Twister), + (HelenH)-[:ACTED_IN {roles:['Dr. Jo Harding']}]->(Twister), + (ZachG)-[:ACTED_IN {roles:['Eddie']}]->(Twister), + (PhilipH)-[:ACTED_IN {roles:['Dustin "Dusty" Davis']}]->(Twister), + (JanB)-[:DIRECTED]->(Twister) + +CREATE (CastAway:Movie {title:'Cast Away', released:2000, tagline:'At the edge of the world, his journey begins.'}) +CREATE (RobertZ:Person {name:'Robert Zemeckis', born:1951}) +CREATE + (TomH)-[:ACTED_IN {roles:['Chuck Noland']}]->(CastAway), + (HelenH)-[:ACTED_IN {roles:['Kelly Frears']}]->(CastAway), + (RobertZ)-[:DIRECTED]->(CastAway) + +CREATE (OneFlewOvertheCuckoosNest:Movie {title:"One Flew Over the Cuckoo's Nest", released:1975, tagline:"If he's crazy, what does that make you?"}) +CREATE (MilosF:Person {name:'Milos Forman', born:1932}) +CREATE + (JackN)-[:ACTED_IN {roles:['Randle McMurphy']}]->(OneFlewOvertheCuckoosNest), + (DannyD)-[:ACTED_IN {roles:['Martini']}]->(OneFlewOvertheCuckoosNest), + (MilosF)-[:DIRECTED]->(OneFlewOvertheCuckoosNest) + +CREATE (SomethingsGottaGive:Movie {title:"Something's Gotta Give", released:2003}) +CREATE (DianeK:Person {name:'Diane Keaton', born:1946}) +CREATE (NancyM:Person {name:'Nancy Meyers', born:1949}) +CREATE + (JackN)-[:ACTED_IN {roles:['Harry Sanborn']}]->(SomethingsGottaGive), + (DianeK)-[:ACTED_IN {roles:['Erica Barry']}]->(SomethingsGottaGive), + (Keanu)-[:ACTED_IN {roles:['Julian Mercer']}]->(SomethingsGottaGive), + (NancyM)-[:DIRECTED]->(SomethingsGottaGive), + (NancyM)-[:PRODUCED]->(SomethingsGottaGive), + (NancyM)-[:WROTE]->(SomethingsGottaGive) + +CREATE (BicentennialMan:Movie {title:'Bicentennial Man', released:1999, tagline:"One robot's 200 year journey to become an ordinary man."}) +CREATE (ChrisC:Person {name:'Chris Columbus', born:1958}) +CREATE + (Robin)-[:ACTED_IN {roles:['Andrew Marin']}]->(BicentennialMan), + (OliverP)-[:ACTED_IN {roles:['Rupert Burns']}]->(BicentennialMan), + (ChrisC)-[:DIRECTED]->(BicentennialMan) + +CREATE (CharlieWilsonsWar:Movie {title:"Charlie Wilson's War", released:2007, tagline:"A stiff drink. A little mascara. A lot of nerve. Who said they couldn't bring down the Soviet empire."}) +CREATE (JuliaR:Person {name:'Julia Roberts', born:1967}) +CREATE + (TomH)-[:ACTED_IN {roles:['Rep. Charlie Wilson']}]->(CharlieWilsonsWar), + (JuliaR)-[:ACTED_IN {roles:['Joanne Herring']}]->(CharlieWilsonsWar), + (PhilipH)-[:ACTED_IN {roles:['Gust Avrakotos']}]->(CharlieWilsonsWar), + (MikeN)-[:DIRECTED]->(CharlieWilsonsWar) + +CREATE (ThePolarExpress:Movie {title:'The Polar Express', released:2004, tagline:'This Holiday Season… Believe'}) +CREATE + (TomH)-[:ACTED_IN {roles:['Hero Boy', 'Father', 'Conductor', 'Hobo', 'Scrooge', 'Santa Claus']}]->(ThePolarExpress), + (RobertZ)-[:DIRECTED]->(ThePolarExpress) + +CREATE (ALeagueofTheirOwn:Movie {title:'A League of Their Own', released:1992, tagline:'Once in a lifetime you get a chance to do something different.'}) +CREATE (Madonna:Person {name:'Madonna', born:1954}) +CREATE (GeenaD:Person {name:'Geena Davis', born:1956}) +CREATE (LoriP:Person {name:'Lori Petty', born:1963}) +CREATE (PennyM:Person {name:'Penny Marshall', born:1943}) +CREATE + (TomH)-[:ACTED_IN {roles:['Jimmy Dugan']}]->(ALeagueofTheirOwn), + (GeenaD)-[:ACTED_IN {roles:['Dottie Hinson']}]->(ALeagueofTheirOwn), + (LoriP)-[:ACTED_IN {roles:['Kit Keller']}]->(ALeagueofTheirOwn), + (RosieO)-[:ACTED_IN {roles:['Doris Murphy']}]->(ALeagueofTheirOwn), + (Madonna)-[:ACTED_IN {roles:['"All the Way" Mae Mordabito']}]->(ALeagueofTheirOwn), + (BillPax)-[:ACTED_IN {roles:['Bob Hinson']}]->(ALeagueofTheirOwn), + (PennyM)-[:DIRECTED]->(ALeagueofTheirOwn) + +CREATE (PaulBlythe:Person {name:'Paul Blythe'}) +CREATE (AngelaScope:Person {name:'Angela Scope'}) +CREATE (JessicaThompson:Person {name:'Jessica Thompson'}) +CREATE (JamesThompson:Person {name:'James Thompson'}) + +CREATE + (JamesThompson)-[:FOLLOWS]->(JessicaThompson), + (AngelaScope)-[:FOLLOWS]->(JessicaThompson), + (PaulBlythe)-[:FOLLOWS]->(AngelaScope) + +CREATE + (JessicaThompson)-[:REVIEWED {summary:'An amazing journey', rating:95}]->(CloudAtlas), + (JessicaThompson)-[:REVIEWED {summary:'Silly, but fun', rating:65}]->(TheReplacements), + (JamesThompson)-[:REVIEWED {summary:'The coolest football movie ever', rating:100}]->(TheReplacements), + (AngelaScope)-[:REVIEWED {summary:'Pretty funny at times', rating:62}]->(TheReplacements), + (JessicaThompson)-[:REVIEWED {summary:'Dark, but compelling', rating:85}]->(Unforgiven), + (JessicaThompson)-[:REVIEWED {summary:"Slapstick redeemed only by the Robin Williams and Gene Hackman's stellar performances", rating:45}]->(TheBirdcage), + (JessicaThompson)-[:REVIEWED {summary:'A solid romp', rating:68}]->(TheDaVinciCode), + (JamesThompson)-[:REVIEWED {summary:'Fun, but a little far fetched', rating:65}]->(TheDaVinciCode), + (JessicaThompson)-[:REVIEWED {summary:'You had me at Jerry', rating:92}]->(JerryMaguire) + +;