Skip to content

Commit

Permalink
Integrate children assertion on nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Patouche committed Feb 23, 2021
1 parent b99358e commit 445c17c
Show file tree
Hide file tree
Showing 25 changed files with 1,597 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,25 @@ public abstract class AbstractEntitiesAssert<SELF extends AbstractEntitiesAssert

/**
* Class constructor.
*
* @param recordType the record type
* @param selfType the self class type
* @param dataLoader the data loader
* @param recordType the record type
* @param entities the entities
* @param selfType the self class type
* @param loader the data loader
* @param newSelfFactory the factory to chain from the current assertion
* @param parentAssert the parent assertion for navigation
* @param rootAssert the parent assertion for navigation
*/
protected AbstractEntitiesAssert(
final ObjectType recordType,
final Class<?> selfType,
final DataLoader<ENTITY> dataLoader,
final List<ENTITY> entities,
final Class<?> selfType,
final DataLoader<ENTITY> loader,
final EntitiesAssertFactory<SELF, ENTITY, NEW_SELF, PARENT_ASSERT, ROOT_ASSERT> 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;
}

/**
Expand Down
160 changes: 158 additions & 2 deletions src/main/java/org/assertj/neo4j/api/beta/AbstractNodesAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
Expand All @@ -46,13 +49,166 @@ public abstract class AbstractNodesAssert<SELF extends AbstractNodesAssert<SELF,
//@formatter:on

protected AbstractNodesAssert(
final Class<SELF> selfType,
final Class<?> selfType,
final List<DbNode> entities,
final DataLoader<DbNode> dataLoader,
final EntitiesAssertFactory<SELF, DbNode, NEW_SELF, PARENT_ASSERT, ROOT_ASSERT> 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<DbNode> emptyLabels(final boolean excludeNoLabels,
final Predicate<Set<String>> 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.
* <p/>
* 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...)}.
* <p/>
* Example:
* <pre><code class='java'>
* Nodes nodes = new Nodes(driver);
* assertThat(nodes)
* .hasSize(14)
* .filteredOnNonEmptyLabels()
* .hasSize(12)
* </code></pre>
*
* @return a new assertion
*/
public NEW_SELF filteredOnNonEmptyLabels() {
return filteredOn(n -> !n.getLabels().isEmpty());
}

/**
* Filter nodes having at least one of the provided labels.
* <p/>
* 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...)}.
* <p/>
* Example:
* <pre><code class='java'>
* Nodes nodes = new Nodes(driver, "Person");
* assertThat(nodes)
* .hasSize(14)
* .filteredOnLabels("TeamMember", "TeamOwner")
* .hasSize(9)
* </code></pre>
*
* @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.
* <p/>
* Example:
* <pre><code class='java'>
* Nodes nodes = new Nodes(driver, "Person");
* assertThat(nodes)
* .hasSize(14)
* .filteredOnLabels(l -> l.startWith("Team"))
* .hasSize(9)
* </code></pre>
*
* @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.
* <p/>
* 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)}.
* <p/>
* Example:
* <pre><code class='java'>
* Nodes nodes = new Nodes(driver, "Person");
* assertThat(nodes)
* .hasSize(14)
* .filteredOnAllLabels(l -> l.startWith("Team"))
* .hasSize(9)
* </code></pre>
*
* @param predicate the predicate that the label should match
* @return a new assertion
*/
public NEW_SELF filteredOnLabelMatchingAny(final Predicate<String> predicate) {
return filteredOnLabelMatchingAny(predicate, false);
}

/**
* Filter nodes having at least one labels matching the predicate.
* <p/>
* Example:
* <pre><code class='java'>
* Nodes nodes = new Nodes(driver);
* assertThat(nodes)
* .hasSize(14)
* .filteredOnAllLabels(l -> l.startWith("Team"), true)
* .hasSize(7)
* </code></pre>
*
* @param predicate the predicate that the label should match
* @return a new assertion
*/
public NEW_SELF filteredOnLabelMatchingAny(final Predicate<String> predicate, boolean excludeNoLabels) {
return filteredOn(emptyLabels(excludeNoLabels, (l) -> l.stream().anyMatch(predicate)));
}

/**
* Filter nodes having all labels matching the predicate.
* <p/>
* 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)}.
* <p/>
* Example:
* <pre><code class='java'>
* Nodes nodes = new Nodes(driver, "AssertJ_Team");
* assertThat(nodes)
* .hasSize(14)
* .filteredOnAllLabels(l -> l.startWith("AssertJ_"))
* .hasSize(7)
* </code></pre>
*
* @param predicate the predicate that the label should match
* @return a new assertion
*/
public NEW_SELF filteredOnLabelMatchingAll(final Predicate<String> predicate) {
return filteredOnLabelMatchingAll(predicate, false);
}

/**
* Filter nodes having all labels matching the predicate.
* <p/>
* Example:
* <pre><code class='java'>
* Nodes nodes = new Nodes(driver, "AssertJ_Team");
* assertThat(nodes)
* .hasSize(14)
* .filteredOnAllLabels(l -> l.startWith("AssertJ_"))
* .hasSize(7)
* </code></pre>
*
* @param predicate the predicate that the label should match
* @return a new assertion
*/
public NEW_SELF filteredOnLabelMatchingAll(final Predicate<String> predicate, boolean excludeNoLabels) {
return filteredOn(emptyLabels(excludeNoLabels, (l) -> l.stream().allMatch(predicate)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,18 +41,17 @@ public abstract class AbstractRelationshipsAssert<SELF extends AbstractRelations
NEW_SELF extends Navigable<SELF, ROOT_ASSERT>,
PARENT_ASSERT extends ParentAssert<ROOT_ASSERT>,
ROOT_ASSERT>
extends AbstractEntitiesAssert<SELF, DbRelationship, NEW_SELF, PARENT_ASSERT, ROOT_ASSERT>
implements Navigable<PARENT_ASSERT, ROOT_ASSERT> {
extends AbstractEntitiesAssert<SELF, DbRelationship, NEW_SELF, PARENT_ASSERT, ROOT_ASSERT> {
//@formatter:on

protected AbstractRelationshipsAssert(
final Class<?> selfType,
final List<DbRelationship> dbRelationships,
final DataLoader<DbRelationship> dbData,
final EntitiesAssertFactory<SELF, DbRelationship, NEW_SELF, PARENT_ASSERT, ROOT_ASSERT> factory,
final List<DbRelationship> entities,
final DataLoader<DbRelationship> loader,
final EntitiesAssertFactory<SELF, DbRelationship, NEW_SELF, PARENT_ASSERT, ROOT_ASSERT> 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);
}

/**
Expand Down Expand Up @@ -80,4 +82,56 @@ public SELF haveAnyOfTypes(final String... types) {
);
}

/**
* Retrieve all nodes that are the start node of any actual relationships.
* <p/>
* Example:
* <pre><code class='java'>
* Relationships relationships = new Relationships(driver, "KNOWS");
* assertThat(relationships)
* .startingNodes("Person")
* .haveLabels("TeamMember")
* </code></pre>
*
* @param labels
* @return
*/
public ChildrenDriverNodeAssert<SELF, ROOT_ASSERT> 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.
* <p/>
* Example:
* <pre><code class='java'>
* Relationships relationships = new Relationships(driver, "KNOWS");
* assertThat(relationships)
* .endingNodes("Person")
* .haveLabels("TeamMember")
* </code></pre>
*
* @param labels
* @return
*/
public ChildrenDriverNodeAssert<SELF, ROOT_ASSERT> 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;
}

}
Original file line number Diff line number Diff line change
@@ -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 <ROOT_ASSERT> the root assertion type
* @param <PARENT_ASSERT> the parent assertion type
* @author Patrick Allain - 02/01/2021
*/
//@formatter:off
public class ChildrenDriverNodeAssert<PARENT_ASSERT extends ParentAssert<ROOT_ASSERT>, ROOT_ASSERT>
extends AbstractNodesAssert<ChildrenDriverNodeAssert<PARENT_ASSERT, ROOT_ASSERT>,
ChildrenDriverNodeAssert<ChildrenDriverNodeAssert<PARENT_ASSERT, ROOT_ASSERT>, ROOT_ASSERT>,
PARENT_ASSERT,
ROOT_ASSERT>
implements Adoptable<ROOT_ASSERT> {
//@formatter:on

protected ChildrenDriverNodeAssert(final List<DbNode> entities,
final DataLoader<DbNode> 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 <NEW_PARENT extends ParentAssert<ROOT_ASSERT>> ChildrenDriverNodeAssert<NEW_PARENT, ROOT_ASSERT> withParent(final NEW_PARENT parentAssert) {
return new ChildrenDriverNodeAssert<>(actual, dataLoader, parentAssert);
}

}
10 changes: 5 additions & 5 deletions src/main/java/org/assertj/neo4j/api/beta/DriverResultAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -121,10 +121,10 @@ public <T> 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<DriverResultAssert, DriverResultAssert> asNodeAssert(final String columnName) {
haveType(columnName, ObjectType.NODE);
final List<DbNode> entities = columnObjects(columnName, ObjectType.NODE, DbNode.class);
return new ChildrenDriverNodeAssert<>(entities, DataLoader.staticDataLoader(), myself);
}

public ChildrenDriverRelationshipsAssert<DriverResultAssert, DriverResultAssert> asRelationshipAssert(final String columnName) {
Expand Down
Loading

0 comments on commit 445c17c

Please sign in to comment.