Skip to content

Commit

Permalink
Remove case sensitivity and node search; fix tests (#792)
Browse files Browse the repository at this point in the history
  • Loading branch information
RichardIrons-neo4j authored Apr 12, 2024
1 parent 625df1e commit c0df8ce
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void ShouldMapSimpleClass()
{
var mapper = DefaultMapper.Get<SimpleClass>();

var record = TestRecord.Create(new[] { "id", "name" }, new object[] { 1, "Foo" });
var record = TestRecord.Create(new[] { "Id", "Name" }, new object[] { 1, "Foo" });
var result = mapper.Map(record);

result.Id.Should().Be(1);
Expand Down Expand Up @@ -293,6 +293,8 @@ public ClassWithProperties(int year, string occurrence)

public int Year { get; set; }
public string Occurrence { get; set; }

[MappingSource("description")]
public string Description { get; set; }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ public class MappingProviderTests
{
private class TestObject
{
[MappingSource("intValue")]
public int IntValue { get; set; }

[MappingSource("texr")]
public string Text { get; set; } = null!;
}

Expand All @@ -42,7 +45,9 @@ private class ThirdTestObject

private class PersonWithAge
{
[MappingSource("name")]
public string Name { get; set; } = null!;

public int Age { get; set; }
}

Expand Down
67 changes: 54 additions & 13 deletions Neo4j.Driver/Neo4j.Driver.Tests/Mapping/RecordMappingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,32 @@ public class RecordMappingTests
{
private class TestPerson
{
[MappingSource("person.name")]
public string Name { get; set; } = "A. Test Name";

[MappingSource("person.born")]
public int? Born { get; set; }

[MappingSource("hobbies")]
public List<string> Hobbies { get; set; } = null!;
}

private class SimpleTestPerson
{
[MappingSource("name")]
public string Name { get; set; } = "A. Test Name";

[MappingSource("born")]
public int? Born { get; set; }

public List<string> Hobbies { get; set; } = null!;
}

[Fact]
public void ShouldMapPrimitives()
{
var record = TestRecord.Create(new[] { "name", "born" }, new object[] { "Bob", 1977 });
var person = record.AsObject<TestPerson>();
var person = record.AsObject<SimpleTestPerson>();
person.Name.Should().Be("Bob");
person.Born.Should().Be(1977);
}
Expand Down Expand Up @@ -72,7 +88,8 @@ public void ShouldMapFromInsideDictionaries()
[Fact]
public void ShouldLeaveDefaultsIfFieldAbsent()
{
var record = TestRecord.Create(new[] { "born" }, new object[] { 1977 });
var dict = new Dictionary<string, object> { { "born", 1977 } };
var record = TestRecord.Create(new[] { "Person" }, new object[] { dict });
var person = RecordObjectMapping.Map(record, typeof(TestPerson)) as TestPerson;
person.Should().NotBeNull();
person!.Name.Should().Be("A. Test Name");
Expand All @@ -81,14 +98,22 @@ public void ShouldLeaveDefaultsIfFieldAbsent()

private class Movie
{
[MappingSource("title")]
public string Title { get; set; } = "";

[MappingSource("released")]
public int Released { get; set; }

[MappingSource("tagline")]
public string Tagline { get; set; }
}

private class Person
{
[MappingSource("name")]
public string Name { get; set; } = "";

[MappingSource("born")]
public int? Born { get; set; }
}

Expand Down Expand Up @@ -216,7 +241,7 @@ Task<EagerResult<IReadOnlyList<IRecord>>> GetRecordsAsync()
}

GetRecordsAsync()
.AsObjectsAsync<TestPerson>()
.AsObjectsAsync<SimpleTestPerson>()
.Result.Should()
.BeEquivalentTo(
new TestPerson { Name = "Bob" },
Expand All @@ -242,7 +267,7 @@ async IAsyncEnumerable<IRecord> GetRecordsAsync()
}
}

var result = await GetRecordsAsync().ToListAsync<TestPerson>();
var result = await GetRecordsAsync().ToListAsync<SimpleTestPerson>();
result.Should()
.BeEquivalentTo(
new TestPerson { Name = "Bob" },
Expand All @@ -268,28 +293,34 @@ async IAsyncEnumerable<IRecord> GetRecordsAsync()
}
}

var people = new List<TestPerson>();
await foreach (var person in GetRecordsAsync().AsObjectsAsync<TestPerson>())
var people = new List<SimpleTestPerson>();
await foreach (var person in GetRecordsAsync().AsObjectsAsync<SimpleTestPerson>())
{
people.Add(person);
}

people.Should()
.BeEquivalentTo(
new TestPerson { Name = "Bob" },
new TestPerson { Name = "Alice", Born = 1988 },
new TestPerson { Name = "Eve", Born = 1999 });
new SimpleTestPerson { Name = "Bob" },
new SimpleTestPerson { Name = "Alice", Born = 1988 },
new SimpleTestPerson { Name = "Eve", Born = 1999 });
}

private class CarAndPainting
{
[MappingSource("car")]
public Car Car { get; set; } = null!;

[MappingSource("painting")]
public Painting Painting { get; set; } = null!;
}

private class Painting
{
[MappingSource("painting.artist")]
public string Artist { get; set; } = "";

[MappingSource("painting.title")]
public string Title { get; set; } = "";
}

Expand All @@ -298,7 +329,7 @@ private class Car
[MappingSource("car.make")]
public string Make { get; set; } = "";

[MappingSource("model")]
[MappingSource("car.model")]
public string Model { get; set; } = "";

[MappingSource("car.madeup")]
Expand Down Expand Up @@ -339,7 +370,9 @@ public void ShouldMapSubNodesWithAbsolutePaths()

private class PersonWithoutBornSetter
{
[MappingSource("name")]
public string Name { get; set; } = "";

public int? Born { get; } = 1999; // no setter
}

Expand All @@ -354,6 +387,7 @@ public void DefaultMapperShouldIgnorePropertiesWithoutSetter()

private class TestPersonWithoutBornMapped
{
[MappingSource("name")]
public string Name { get; set; } = "A. Test Name";

[MappingIgnored]
Expand All @@ -371,12 +405,16 @@ public void ShouldIgnorePropertiesWithDoNotMapAttribute()

private class Book
{
[MappingSource("title")]
public string Title { get; set; }
}

private class Author
{
[MappingSource("author.name")]
public string Name { get; set; }

[MappingSource("author.books")]
public List<Book> Books { get; set; }
}

Expand Down Expand Up @@ -406,8 +444,8 @@ public void ShouldMapEntitiesWithListsOfNodes()

private record Song(
[MappingSource("recordingArtist")] string Artist,
string Title,
int Year);
[MappingSource("title")] string Title,
[MappingSource("year")] int Year);

[Fact]
public void ShouldMapToRecords()
Expand Down Expand Up @@ -448,7 +486,10 @@ public void ShouldFailMappingToRecordsWithMissingFields()

private class ClassWithInitProperties
{
[MappingSource("name")]
public string Name { get; init; } = "";

[MappingSource("age")]
public int Age { get; init; }
}

Expand Down Expand Up @@ -525,7 +566,7 @@ public void ShouldMapEntityToObjectThroughAsRecord()

var record = node.AsRecord();

var person = record.AsObject<TestPerson>();
var person = record.AsObject<SimpleTestPerson>();
person.Name.Should().Be("Bob");
person.Born.Should().Be(1977);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void TryGetValueByPath_PathMatchesFieldName_ReturnsTrue()
var recordPathFinder = new RecordPathFinder();
var record = TestRecord.Create(new[] { "testField" }, new object[] { "testValue" });

var result = recordPathFinder.TryGetValueByPath(record, "TesTfIELd", out var value);
var result = recordPathFinder.TryGetValueByPath(record, "testField", out var value);

result.Should().BeTrue();
value.Should().Be("testValue");
Expand Down
3 changes: 1 addition & 2 deletions Neo4j.Driver/Neo4j.Driver/Internal/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@ public async Task<ExecutionSummary> GetRowsAsync(
Query query,
QueryConfig config,
Action<IRecord> streamProcessor,
CancellationToken cancellationToken
)
CancellationToken cancellationToken)
{
async Task<int> Process(IAsyncEnumerable<IRecord> records)
{
Expand Down
19 changes: 1 addition & 18 deletions Neo4j.Driver/Neo4j.Driver/Preview/Mapping/RecordPathFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public bool TryGetValueByPath(IRecord record, string path, out object value)
}

// if the path matches a field name, we can return the value directly
if (record.TryGetCaseInsensitive(path, out value))
if (record.TryGet(path, out value))
{
return true;
}
Expand Down Expand Up @@ -66,23 +66,6 @@ public bool TryGetValueByPath(IRecord record, string path, out object value)
}
}

// check any values on the record that are entities or dictionaries, in case
// the path is a property on one of those
foreach (var key in record.Keys)
{
var dictAsRecord = record[key] switch
{
IEntity entity => new DictAsRecord(entity.Properties, record),
IReadOnlyDictionary<string, object> dict => new DictAsRecord(dict, record),
_ => null
};

if(dictAsRecord is not null && TryGetValueByPath(dictAsRecord, path, out value))
{
return true;
}
}

return false;
}
}

0 comments on commit c0df8ce

Please sign in to comment.