Skip to content

Commit

Permalink
Fix LT-21674 linebreak issue and add tests
Browse files Browse the repository at this point in the history
* Process the before after content looking for linebreak
  characters
* Add unit testing class for LcmWordGenerator
  • Loading branch information
jasonleenaylor committed Jul 3, 2024
1 parent ebd13d1 commit 8c0cdf7
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Src/xWorks/LcmWordGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using XmlDrawing = DocumentFormat.OpenXml.Drawing;
using DrawingWP = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using Pictures = DocumentFormat.OpenXml.Drawing.Pictures;
using System.Text.RegularExpressions;

namespace SIL.FieldWorks.XWorks
{
Expand Down Expand Up @@ -1754,6 +1755,25 @@ private WP.Run CreateRun(string runText, string styleDisplayName)
/// <returns>The BeforeAfterBetween run.</returns>
private WP.Run CreateBeforeAfterBetweenRun(string text)
{
if(text.Contains("\\A"))
{
var run = new WP.Run()
{
RunProperties = new WP.RunProperties(new RunStyle() { Val = WordStylesGenerator.BeforeAfterBetweenDisplayName })
};
// If the before after between text has line break characters return a composite run including theline breaks
// Use Regex.Matches to capture both the content and the delimiters
var matches = Regex.Matches(text, @"(\\A|\\0A)|[^\\]*(?:(?=\\A|\\0A)|$)");
foreach (Match match in matches)
{
if (match.Groups[1].Success)
run.Append(new WP.Break() { Type = BreakValues.TextWrapping });
else
run.Append(new WP.Text(match.Value));
}
return run;
}

return CreateRun(text, WordStylesGenerator.BeforeAfterBetweenDisplayName);
}

Expand Down
217 changes: 217 additions & 0 deletions Src/xWorks/xWorksTests/LcmWordGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
// Copyright (c) 2020-2023 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms.VisualStyles;
using System.Xml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using NUnit.Framework;
using SIL.FieldWorks.Common.Framework;
using SIL.FieldWorks.Common.FwUtils;
using SIL.FieldWorks.Common.Widgets;
using SIL.LCModel;
using SIL.LCModel.Application;
using SIL.LCModel.DomainImpl;
using SIL.LCModel.DomainServices;
using SIL.TestUtilities;
using XCore;
using static SIL.FieldWorks.XWorks.LcmWordGenerator;
// ReSharper disable StringLiteralTypo

namespace SIL.FieldWorks.XWorks
{
[TestFixture]
class LcmWordGeneratorTests : MemoryOnlyBackendProviderRestoredForEachTestTestBase, IDisposable
{
private FwXApp m_application;
private FwXWindow m_window;
private PropertyTable m_propertyTable;
private Mediator m_mediator;
private RecordClerk m_Clerk;

private const string DictionaryNormal = "Dictionary-Normal";

private ConfiguredLcmGenerator.GeneratorSettings DefaultSettings;

private static XmlNamespaceManager WordNamespaceManager;

static LcmWordGeneratorTests()
{
var openXmlSchema = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
WordNamespaceManager = new XmlNamespaceManager(new NameTable());
WordNamespaceManager.AddNamespace("w", openXmlSchema);
WordNamespaceManager.AddNamespace("r", openXmlSchema);
WordNamespaceManager.AddNamespace("wp", openXmlSchema);
}

[OneTimeSetUp]
public override void FixtureSetup()
{
base.FixtureSetup();
FwRegistrySettings.Init();
m_application = new MockFwXApp(new MockFwManager { Cache = Cache }, null, null);
var m_configFilePath = Path.Combine(FwDirectoryFinder.CodeDirectory, m_application.DefaultConfigurationPathname);
m_window = new MockFwXWindow(m_application, m_configFilePath);
((MockFwXWindow)m_window).Init(Cache); // initializes Mediator values
m_propertyTable = m_window.PropTable;
m_mediator = m_window.Mediator;
m_window.LoadUI(m_configFilePath); // actually loads UI here; needed for non-null stylesheet
var wordGenerator = new LcmWordGenerator(Cache);
wordGenerator.Init(new ReadOnlyPropertyTable(m_propertyTable));
DefaultSettings = new ConfiguredLcmGenerator.GeneratorSettings(Cache,
new ReadOnlyPropertyTable(m_propertyTable), true, false, null)
{ ContentGenerator = wordGenerator, StylesGenerator = wordGenerator };

var styles = FontHeightAdjuster.StyleSheetFromPropertyTable(m_propertyTable).Styles;
if (!styles.Contains(DictionaryNormal))
styles.Add(new BaseStyleInfo { Name = DictionaryNormal });
if (!styles.Contains("Dictionary-Headword"))
styles.Add(new BaseStyleInfo { Name = "Dictionary-Headword", IsParagraphStyle = false});

m_Clerk = CreateClerk();
m_propertyTable.SetProperty("ActiveClerk", m_Clerk, false);

m_propertyTable.SetProperty("currentContentControl", "lexiconDictionary", false);
Cache.ProjectId.Path = Path.Combine(FwDirectoryFinder.SourceDirectory, "xWorks/xWorksTests/TestData/");
}

private RecordClerk CreateClerk()
{
const string entryClerk = @"<?xml version='1.0' encoding='UTF-8'?>
<root>
<clerks>
<clerk id='entries'>
<recordList owner='LexDb' property='Entries'/>
</clerk>
</clerks>
<tools>
<tool label='Dictionary' value='lexiconDictionary' icon='DocumentView'>
<control>
<dynamicloaderinfo assemblyPath='xWorks.dll' class='SIL.FieldWorks.XWorks.XhtmlDocView'/>
<parameters area='lexicon' clerk='entries' layout='Bartholomew' layoutProperty='DictionaryPublicationLayout' editable='false' configureObjectName='Dictionary'/>
</control>
</tool>
</tools>
</root>";
var doc = new XmlDocument();
doc.LoadXml(entryClerk);
XmlNode clerkNode = doc.SelectSingleNode("//tools/tool[@label='Dictionary']//parameters[@area='lexicon']");
RecordClerk clerk = RecordClerkFactory.CreateClerk(m_mediator, m_propertyTable, clerkNode, false);
clerk.SortName = "Headword";
return clerk;
}
#region disposal
protected virtual void Dispose(bool disposing)
{
System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** ");
if (disposing)
{
m_Clerk?.Dispose();
m_application?.Dispose();
m_window?.Dispose();
m_mediator?.Dispose();
m_propertyTable?.Dispose();
}
}

~LcmWordGeneratorTests()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
#endregion disposal

[OneTimeTearDown]
public override void FixtureTeardown()
{
base.FixtureTeardown();
Dispose();
}


[Test]
public void GenerateWordDocForEntry_OneSenseWithGlossGeneratesCorrectResult()
{
var wsOpts = ConfiguredXHTMLGeneratorTests.GetWsOptionsForLanguages(new[] { "en" });
var glossNode = new ConfigurableDictionaryNode
{
FieldDescription = "Gloss",
DictionaryNodeOptions = wsOpts,
Style = "Dictionary-Headword"
};
var sensesNode = new ConfigurableDictionaryNode
{
FieldDescription = "Senses",
DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetSenseNodeOptions(),
Children = new List<ConfigurableDictionaryNode> { glossNode },
Style = DictionaryNormal
};
var mainEntryNode = new ConfigurableDictionaryNode
{
Children = new List<ConfigurableDictionaryNode> { sensesNode },
FieldDescription = "LexEntry",
Style = DictionaryNormal
};
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode);
var entry = ConfiguredXHTMLGeneratorTests.CreateInterestingLexEntry(Cache);

//SUT
var result = ConfiguredLcmGenerator.GenerateContentForEntry(entry, mainEntryNode, null, DefaultSettings, 0) as DocFragment;
Console.WriteLine(result);
AssertThatXmlIn.String(result.mainDocPart.RootElement.OuterXml).HasSpecifiedNumberOfMatchesForXpath(
"/w:document/w:body/w:p/w:r/w:t[text()='gloss']",
1,
WordNamespaceManager);
}

[Test]
public void GenerateWordDocForEntry_LineBreaksInBeforeContentWork()
{
var wsOpts = ConfiguredXHTMLGeneratorTests.GetWsOptionsForLanguages(new[] { "en" });
var glossNode = new ConfigurableDictionaryNode
{
FieldDescription = "Gloss",
DictionaryNodeOptions = wsOpts,
Style = "Dictionary-Headword",
Before = "\\Abefore\\0A"
};
var sensesNode = new ConfigurableDictionaryNode
{
FieldDescription = "Senses",
DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetSenseNodeOptions(),
Children = new List<ConfigurableDictionaryNode> { glossNode },
Style = DictionaryNormal
};
var mainEntryNode = new ConfigurableDictionaryNode
{
Children = new List<ConfigurableDictionaryNode> { sensesNode },
FieldDescription = "LexEntry",
Style = DictionaryNormal
};
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode);
var entry = ConfiguredXHTMLGeneratorTests.CreateInterestingLexEntry(Cache);
//SUT
var result = ConfiguredLcmGenerator.GenerateContentForEntry(entry, mainEntryNode, null, DefaultSettings, 0) as DocFragment;
Console.WriteLine(result);
AssertThatXmlIn.String(result?.mainDocPart.RootElement?.OuterXml).HasSpecifiedNumberOfMatchesForXpath(
"/w:document/w:body/w:p/w:r/w:br[@w:type='textWrapping']",
2,
WordNamespaceManager);
}
}
}
5 changes: 5 additions & 0 deletions Src/xWorks/xWorksTests/xWorksTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="DocumentFormat.OpenXml, Version=2.20.0.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\Output\Debug\DocumentFormat.OpenXml.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
Expand Down Expand Up @@ -308,6 +312,7 @@
<Compile Include="InterestingTextsTests.cs" />
<Compile Include="ItemClickedTests.cs" />
<Compile Include="LcmJsonGeneratorTests.cs" />
<Compile Include="LcmWordGeneratorTests.cs" />
<Compile Include="MacroListenerTests.cs" />
<Compile Include="RecordListTests.cs" />
<Compile Include="ReversalIndexServicesTests.cs" />
Expand Down

0 comments on commit 8c0cdf7

Please sign in to comment.