Skip to content

Commit 388d4c0

Browse files
authored
Use normalization wrapper in js-invokable (#2068)
* Use unicode normalized api in tests by default * Move normalization wrapper to correct namespace * Use normalization wrapper in MiniLcmJsInvokable * Extend query tests to cover normalization
1 parent b14afd2 commit 388d4c0

File tree

15 files changed

+90
-38
lines changed

15 files changed

+90
-38
lines changed

backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/BasicApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public async Task GetEntry_WithNullLexemeFormOA_CreatesNewLexemeForm()
2222
LexemeForm = new MultiString { { "en", "test" } }
2323
});
2424

25-
var fwApi = (FwDataMiniLcmApi)Api;
25+
var fwApi = (FwDataMiniLcmApi)BaseApi;
2626
var lexEntry = fwApi.EntriesRepository.GetObject(entry.Id);
2727
UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW("Set LexemeFormOA to null",
2828
"Restore LexemeFormOA",

backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/ComplexFormComponentTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected override Task<IMiniLcmApi> NewApi()
2727
public override async Task InitializeAsync()
2828
{
2929
await base.InitializeAsync();
30-
var fwDataApi = (FwDataMiniLcmApi)Api;
30+
var fwDataApi = (FwDataMiniLcmApi)BaseApi;
3131
var complexFormEntry = fwDataApi.EntriesRepository.GetObject(_complexFormEntryId);
3232
await fwDataApi.Cache.DoUsingNewOrCurrentUOW("Add ComplexFormEntryRef",
3333
"Remove ComplexFormEntryRef",
@@ -69,7 +69,7 @@ public async Task DuplicateComplexFormComponents_BothAreRemoved()
6969

7070
private async Task AddDuplicateComponent()
7171
{
72-
var fwDataApi = (FwDataMiniLcmApi)Api;
72+
var fwDataApi = (FwDataMiniLcmApi)BaseApi;
7373
var complexFormEntry = fwDataApi.EntriesRepository.GetObject(_complexFormEntryId);
7474
var componentEntry = fwDataApi.EntriesRepository.GetObject(_componentEntryId);
7575
await fwDataApi.Cache.DoUsingNewOrCurrentUOW("Add ComplexFormEntryRef",
@@ -107,7 +107,7 @@ public async Task DuplicateComplexFormTypes_BothAreRemoved()
107107

108108
private async Task AddDuplicateFormType()
109109
{
110-
var fwDataApi = (FwDataMiniLcmApi)Api;
110+
var fwDataApi = (FwDataMiniLcmApi)BaseApi;
111111
var complexFormEntry = fwDataApi.EntriesRepository.GetObject(_complexFormEntryId);
112112
var complexFormType = fwDataApi.ComplexFormTypesFlattened.First();
113113
await fwDataApi.Cache.DoUsingNewOrCurrentUOW("Add ComplexFormEntryRef",

backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/CreateEntryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ protected override Task<IMiniLcmApi> NewApi()
1717
public async Task CreateEntry_SetsMorphType()
1818
{
1919
var entry = await Api.CreateEntry(new Entry() { LexemeForm = { ["en"] = "test" } });
20-
var fwDataApi = (FwDataMiniLcmApi)Api;
20+
var fwDataApi = (FwDataMiniLcmApi)BaseApi;
2121
var lexEntry = fwDataApi.EntriesRepository.GetObject(entry.Id);
2222
lexEntry.Should().NotBeNull();
2323
lexEntry.LexemeFormOA.MorphTypeRA.Should().NotBeNull();

backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/MediaTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ protected override Task<IMiniLcmApi> NewApi()
2121
public override async Task InitializeAsync()
2222
{
2323
await base.InitializeAsync();
24-
var projectFolder = ((FwDataMiniLcmApi)Api).Cache.LangProject.LinkedFilesRootDir;
24+
var projectFolder = ((FwDataMiniLcmApi)BaseApi).Cache.LangProject.LinkedFilesRootDir;
2525
Directory.CreateDirectory(projectFolder);
2626
}
2727

2828
public override async Task DisposeAsync()
2929
{
30-
var projectFolder = ((FwDataMiniLcmApi)Api).Cache.ProjectId.ProjectFolder;
30+
var projectFolder = ((FwDataMiniLcmApi)BaseApi).Cache.ProjectId.ProjectFolder;
3131
if (Directory.Exists(projectFolder)) Directory.Delete(projectFolder, true);
3232
await base.DisposeAsync();
3333
}

backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/PartOfSpeechTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public async Task SetPartOfSpeech_WithNullMorphoSyntaxAnalysisRA_ToValidPos()
2626
]
2727
});
2828

29-
var fwApi = (FwDataMiniLcmApi)Api;
29+
var fwApi = (FwDataMiniLcmApi)BaseApi;
3030
var lexEntry = fwApi.EntriesRepository.GetObject(entry.Id);
3131
var lexSense = lexEntry.SensesOS.First();
3232
UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW("Set MorphoSyntaxAnalysisRA to null",
@@ -61,7 +61,7 @@ public async Task SetPartOfSpeech_WithNullMorphoSyntaxAnalysisRA_ToNull()
6161
]
6262
});
6363

64-
var fwApi = (FwDataMiniLcmApi)Api;
64+
var fwApi = (FwDataMiniLcmApi)BaseApi;
6565
var lexEntry = fwApi.EntriesRepository.GetObject(entry.Id);
6666
var lexSense = lexEntry.SensesOS.First();
6767
UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW("Set MorphoSyntaxAnalysisRA to null",

backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/QueryEntryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public override async Task InitializeAsync()
1313
await base.InitializeAsync();
1414
var entry = await Api.CreateEntry(new Entry { LexemeForm = new MultiString { { "en", "test" } } });
1515

16-
var fwApi = (FwDataMiniLcmApi)Api;
16+
var fwApi = (FwDataMiniLcmApi)BaseApi;
1717
var lexEntry = fwApi.EntriesRepository.GetObject(entry.Id);
1818
UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW("Set LexemeFormOA to null",
1919
"Restore LexemeFormOA",

backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/UpdateEntryTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public async Task UpdateEntry_WithNullLexemeFormOA_CreatesNewLexemeForm()
2626
LexemeForm = new MultiString { { "en", "test" } }
2727
});
2828

29-
var fwApi = (FwDataMiniLcmApi)Api;
29+
var fwApi = (FwDataMiniLcmApi)BaseApi;
3030
var lexEntry = fwApi.EntriesRepository.GetObject(entry.Id);
3131
UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW("Set LexemeFormOA to null",
3232
"Restore LexemeFormOA",
@@ -75,7 +75,7 @@ public async Task UpdateEntry_CanUpdateExampleSentenceTranslations_WhenNoTransla
7575
]
7676
});
7777

78-
var fwApi = (FwDataMiniLcmApi)Api;
78+
var fwApi = (FwDataMiniLcmApi)BaseApi;
7979
var lexEntry = fwApi.EntriesRepository.GetObject(entry.Id);
8080
lexEntry.SensesOS[0].ExamplesOS[0].TranslationsOC.Should().BeEmpty();
8181

@@ -115,7 +115,7 @@ await Api.CreateEntry(new Entry
115115
]
116116
});
117117

118-
var fwApi = (FwDataMiniLcmApi)Api;
118+
var fwApi = (FwDataMiniLcmApi)BaseApi;
119119
var lexEntry = fwApi.EntriesRepository.GetObject(entryId);
120120
var senseFactory = fwApi.Cache.ServiceLocator.GetInstance<ILexSenseFactory>();
121121
UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW("Add subsenses to sense 1",
@@ -178,7 +178,7 @@ await Api.CreateEntry(new Entry
178178
]
179179
});
180180

181-
var fwApi = (FwDataMiniLcmApi)Api;
181+
var fwApi = (FwDataMiniLcmApi)BaseApi;
182182
var lexEntry = fwApi.EntriesRepository.GetObject(entryId);
183183
var senseFactory = fwApi.Cache.ServiceLocator.GetInstance<ILexSenseFactory>();
184184
UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW("Add subsenses to sense 1",

backend/FwLite/FwLiteProjectSync.Tests/EntrySyncTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Text;
12
using FwLiteProjectSync.Tests.Fixtures;
23
using MiniLcm;
34
using MiniLcm.Models;
@@ -66,6 +67,39 @@ public Task DisposeAsync()
6667
private readonly SyncFixture _fixture = fixture;
6768
protected IMiniLcmApi Api = null!;
6869

70+
[Fact]
71+
public async Task NormalizesStringsToNFD()
72+
{
73+
// arrange
74+
var formC = "ймыл";
75+
var formD = "ймыл";
76+
77+
formC.Should().NotBe(formD);
78+
formC.Should().Be(formC.Normalize(NormalizationForm.FormC));
79+
formD.Should().Be(formD.Normalize(NormalizationForm.FormD));
80+
formC.Normalize(NormalizationForm.FormD).Should().Be(formD);
81+
82+
var entry1Id = Guid.NewGuid();
83+
await Api.CreateEntry(new() { Id = entry1Id });
84+
var entry1_before_formC = new Entry() { Id = entry1Id, LexemeForm = { { "en", formC } } };
85+
var entry1_after_formD = new Entry() { Id = entry1Id, LexemeForm = { { "en", formD } } };
86+
87+
var entry2Id = Guid.NewGuid();
88+
var entry2_new_formC = new Entry() { Id = entry2Id, LexemeForm = { { "en", formC } } };
89+
90+
// act
91+
await EntrySync.SyncWithoutComplexFormsAndComponents(
92+
[entry1_before_formC],
93+
[entry1_after_formD, entry2_new_formC], Api);
94+
95+
// assert
96+
var entry1After = await Api.GetEntry(entry1Id);
97+
entry1After!.LexemeForm["en"].Should().Be(formD);
98+
// this fails for crdt - https://github.com/sillsdev/languageforge-lexbox/issues/2065
99+
// var entry2After = await Api.GetEntry(entry2Id);
100+
// entry2After!.LexemeForm["en"].Should().Be(formD);
101+
}
102+
69103
[Fact]
70104
public async Task CanChangeComplexFormViaSync_Components()
71105
{

backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.Extensions.Logging;
88
using Microsoft.Extensions.Options;
99
using MiniLcm;
10+
using MiniLcm.Normalization;
1011
using MiniLcm.SyncHelpers;
1112
using MiniLcm.Validators;
1213
using SIL.Harmony;

backend/FwLite/FwLiteShared/Services/MiniLcmJsInvokable.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using MiniLcm;
66
using MiniLcm.Media;
77
using MiniLcm.Models;
8+
using MiniLcm.Normalization;
89
using MiniLcm.Validators;
910
using MiniLcm.Wrappers;
1011
using Reinforced.Typings.Attributes;
@@ -17,9 +18,11 @@ public class MiniLcmJsInvokable(
1718
IProjectIdentifier project,
1819
ILogger<MiniLcmJsInvokable> logger,
1920
MiniLcmApiNotifyWrapperFactory notificationWrapperFactory,
20-
MiniLcmApiValidationWrapperFactory validationWrapperFactory) : IDisposable
21+
MiniLcmApiValidationWrapperFactory validationWrapperFactory,
22+
MiniLcmApiStringNormalizationWrapperFactory normalizationWrapperFactory
23+
) : IDisposable
2124
{
22-
private readonly IMiniLcmApi _wrappedApi = api.WrapWith([validationWrapperFactory, notificationWrapperFactory], project);
25+
private readonly IMiniLcmApi _wrappedApi = api.WrapWith([normalizationWrapperFactory, validationWrapperFactory, notificationWrapperFactory], project);
2326

2427
public record MiniLcmFeatures(bool? History, bool? Write, bool? OpenWithFlex, bool? Feedback, bool? Sync, bool? Audio);
2528
private bool SupportsSync => project.DataFormat == ProjectDataFormat.Harmony && api is CrdtMiniLcmApi;

0 commit comments

Comments
 (0)