Skip to content

Commit db3ba6b

Browse files
authored
Make fwdata api respect nullable return types (#2048)
* Add failing tests * Make fwdata api respect nullable return types
1 parent 0d076c6 commit db3ba6b

File tree

7 files changed

+156
-5
lines changed

7 files changed

+156
-5
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using FwDataMiniLcmBridge.Tests.Fixtures;
2+
3+
namespace FwDataMiniLcmBridge.Tests.MiniLcmTests;
4+
5+
[Collection(ProjectLoaderFixture.Name)]
6+
public class SenseTests(ProjectLoaderFixture fixture) : SenseTestsBase
7+
{
8+
protected override Task<IMiniLcmApi> NewApi()
9+
{
10+
return Task.FromResult<IMiniLcmApi>(fixture.NewProjectApi("SenseTests", "en", "en"));
11+
}
12+
}

backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,8 @@ public IAsyncEnumerable<Entry> SearchEntries(string query, QueryOptions? options
953953

954954
public Task<Entry?> GetEntry(Guid id)
955955
{
956-
return Task.FromResult<Entry?>(FromLexEntry(EntriesRepository.GetObject(id)));
956+
EntriesRepository.TryGetObject(id, out var lexEntry);
957+
return Task.FromResult(lexEntry is null ? null : FromLexEntry(lexEntry));
957958
}
958959

959960
public async Task<Entry> CreateEntry(Entry entry, CreateEntryOptions? options = null)
@@ -1423,7 +1424,7 @@ private void ApplySenseToLexSense(Sense sense, ILexSense lexSense)
14231424

14241425
public Task<Sense?> GetSense(Guid entryId, Guid id)
14251426
{
1426-
var lcmSense = SenseRepository.GetObject(id);
1427+
SenseRepository.TryGetObject(id, out var lcmSense);
14271428
return Task.FromResult(lcmSense is null ? null : FromLexSense(lcmSense));
14281429
}
14291430

@@ -1550,7 +1551,7 @@ public Task DeleteSense(Guid entryId, Guid senseId)
15501551

15511552
public Task<ExampleSentence?> GetExampleSentence(Guid entryId, Guid senseId, Guid id)
15521553
{
1553-
var lcmExampleSentence = ExampleSentenceRepository.GetObject(id);
1554+
ExampleSentenceRepository.TryGetObject(id, out var lcmExampleSentence);
15541555
return Task.FromResult(lcmExampleSentence is null ? null : FromLexExampleSentence(senseId, lcmExampleSentence));
15551556
}
15561557

backend/FwLite/FwLiteProjectSync.Tests/CrdtRepairTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,25 @@ public async Task CrdtEntryMissingTranslationId_FwTranslationRemoved_FullSync()
214214
updatedCrdtEntry!.SingleExampleSentence().Translations.Should().BeEmpty();
215215
}
216216

217+
[Fact]
218+
public async Task CrdtEntryMissingTranslationId_FwExampleSentenceRemoved_FullSync()
219+
{
220+
// arrange
221+
var (fwEntry, crdtEntry, _) = await CreateSyncedEntryMissingTranslationId();
222+
var entryId = fwEntry.Id;
223+
var senseId = fwEntry.Senses.Single().Id;
224+
var exampleSentenceId = fwEntry.SingleExampleSentence().Id;
225+
226+
// act
227+
await FwDataApi.DeleteExampleSentence(entryId, senseId, exampleSentenceId);
228+
var result = await SyncService.Sync(CrdtApi, FwDataApi);
229+
result.CrdtChanges.Should().Be(1, "the crdt example-sentence was removed");
230+
231+
// assert - the crdt translation was also removed
232+
var updatedCrdtEntry = await CrdtApi.GetEntry(crdtEntry.Id);
233+
updatedCrdtEntry!.Senses.Single().ExampleSentences.Should().BeEmpty();
234+
}
235+
217236
[Fact]
218237
public async Task CrdtEntryMissingTranslationId_CrdtTranslationRemoved_SyncMissingTranslationIds()
219238
{
@@ -255,6 +274,24 @@ public async Task CrdtEntryMissingTranslationId_CrdtTranslationRemoved_FullSync(
255274
updatedFwEntry!.SingleExampleSentence().Translations.Should().BeEmpty();
256275
}
257276

277+
[Fact]
278+
public async Task CrdtEntryMissingTranslationId_CrdtExampleSentenceRemoved_FullSync()
279+
{
280+
// arrange
281+
var (fwEntry, crdtEntry, _) = await CreateSyncedEntryMissingTranslationId();
282+
var entryId = fwEntry.Id;
283+
var senseId = fwEntry.Senses.Single().Id;
284+
var exampleSentenceId = fwEntry.SingleExampleSentence().Id;
285+
286+
// act
287+
await CrdtApi.DeleteExampleSentence(entryId, senseId, exampleSentenceId);
288+
await SyncService.Sync(CrdtApi, FwDataApi);
289+
290+
// assert - the fw translation was also removed
291+
var updatedFwEntry = await FwDataApi.GetEntry(crdtEntry.Id);
292+
updatedFwEntry!.Senses.Single().ExampleSentences.Should().BeEmpty();
293+
}
294+
258295
[Fact]
259296
public async Task CrdtEntryMissingTranslationId_NewCrdtEntry_SyncMissingTranslationIds()
260297
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace LcmCrdt.Tests.MiniLcmTests;
2+
3+
public class SenseTests : SenseTestsBase
4+
{
5+
private readonly MiniLcmApiFixture _fixture = new();
6+
7+
protected override async Task<IMiniLcmApi> NewApi()
8+
{
9+
await _fixture.InitializeAsync();
10+
var api = _fixture.Api;
11+
return api;
12+
}
13+
14+
public override async Task DisposeAsync()
15+
{
16+
await base.DisposeAsync();
17+
await _fixture.DisposeAsync();
18+
}
19+
}

backend/FwLite/MiniLcm.Tests/ExampleSentenceTestsBase.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public abstract class ExampleSentenceTestsBase : MiniLcmTestBase
44
{
55
private readonly Guid _entryId = Guid.NewGuid();
66
private readonly Guid _senseId = Guid.NewGuid();
7+
private readonly Guid _exampleSentenceId = Guid.NewGuid();
78

89
public override async Task InitializeAsync()
910
{
@@ -14,11 +15,35 @@ await Api.CreateEntry(new Entry()
1415
LexemeForm = { { "en", "new-lexeme-form" } },
1516
Senses =
1617
[
17-
new Sense() { Id = _senseId, Gloss = { { "en", "new-sense-gloss" } } }
18+
new Sense()
19+
{
20+
Id = _senseId,
21+
Gloss = { { "en", "new-sense-gloss" } },
22+
ExampleSentences = [ new()
23+
{
24+
Id = _exampleSentenceId,
25+
Sentence = { { "en", new("new-example-sentence") } },
26+
}]
27+
}
1828
]
1929
});
2030
}
2131

32+
[Fact]
33+
public async Task Get_MissingExampleSentence_ReturnsNull()
34+
{
35+
var exampleSentence = await Api.GetExampleSentence(_entryId, _senseId, Guid.NewGuid());
36+
exampleSentence.Should().BeNull();
37+
}
38+
39+
[Fact]
40+
public async Task Get_ExistingExampleSentence_ReturnsExampleSentence()
41+
{
42+
var exampleSentence = await Api.GetExampleSentence(_entryId, _senseId, _exampleSentenceId);
43+
exampleSentence.Should().NotBeNull();
44+
exampleSentence.Sentence["en"].Should().BeEquivalentTo(new RichString("new-example-sentence", "en"));
45+
}
46+
2247
[Fact]
2348
public async Task CanCreateExampleSentence()
2449
{

backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace MiniLcm.Tests;
66

77
public abstract class QueryEntryTestsBase : MiniLcmTestBase
88
{
9+
private readonly Guid appleId = Guid.NewGuid();
910
private readonly string Apple = "Apple";
1011
private readonly string Peach = "Peach";
1112
private readonly string Banana = "Banana";
@@ -23,7 +24,11 @@ public override async Task InitializeAsync()
2324
await Api.CreateSemanticDomain(semanticDomain);
2425
var complexFormType = new ComplexFormType() { Id = Guid.NewGuid(), Name = new() { { "en", "Very complex" } } };
2526
await Api.CreateComplexFormType(complexFormType);
26-
await Api.CreateEntry(new Entry() { LexemeForm = { { "en", Apple } } });
27+
await Api.CreateEntry(new Entry()
28+
{
29+
Id = appleId,
30+
LexemeForm = { { "en", Apple } }
31+
});
2732
await Api.CreateEntry(new Entry()
2833
{
2934
LexemeForm = { { "en", Peach } },
@@ -92,6 +97,21 @@ await Api.CreateEntry(new Entry()
9297
await Api.CreateEntry(new Entry());
9398
}
9499

100+
[Fact]
101+
public async Task Get_MissingEntry_ReturnsNull()
102+
{
103+
var entry = await Api.GetEntry(Guid.NewGuid());
104+
entry.Should().BeNull();
105+
}
106+
107+
[Fact]
108+
public async Task Get_ExistingEntry_ReturnsEntry()
109+
{
110+
var entry = await Api.GetEntry(appleId);
111+
entry.Should().NotBeNull();
112+
entry.LexemeForm["en"].Should().Be(Apple);
113+
}
114+
95115
[Fact]
96116
public async Task CanFilterToMissingSenses()
97117
{
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace MiniLcm.Tests;
2+
3+
public abstract class SenseTestsBase : MiniLcmTestBase
4+
{
5+
private static readonly Guid _entryId = Guid.NewGuid();
6+
private static readonly Guid _senseId = Guid.NewGuid();
7+
8+
public override async Task InitializeAsync()
9+
{
10+
await base.InitializeAsync();
11+
await Api.CreateEntry(new Entry()
12+
{
13+
Id = _entryId,
14+
LexemeForm = { { "en", "new-lexeme-form" } },
15+
Senses = [new()
16+
{
17+
Id = _senseId,
18+
Gloss = { { "en", "new-sense-gloss" } }
19+
}]
20+
});
21+
}
22+
23+
[Fact]
24+
public async Task Get_MissingSense_ReturnsNull()
25+
{
26+
var sense = await Api.GetSense(_entryId, Guid.NewGuid());
27+
sense.Should().BeNull();
28+
}
29+
30+
[Fact]
31+
public async Task Get_ExistingSense_ReturnsSense()
32+
{
33+
var sense = await Api.GetSense(_entryId, _senseId);
34+
sense.Should().NotBeNull();
35+
sense.Gloss["en"].Should().Be("new-sense-gloss");
36+
}
37+
}

0 commit comments

Comments
 (0)