Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Src/LexText/LexTextDll/AreaListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ protected virtual void Dispose(bool disposing)
Subscriber.Unsubscribe(EventConstants.SetToolFromName, SetToolFromName);
Subscriber.Unsubscribe(EventConstants.ReloadAreaTools, ReloadAreaTools);
Subscriber.Unsubscribe(EventConstants.GetContentControlParameters, GetContentControlParameters);
Subscriber.Unsubscribe(EventConstants.GetToolForList, GetToolForList);
Subscriber.Unsubscribe(EventConstants.SetInitialContentObject, SetInitialContentObject);

// Dispose managed resources here.
Expand Down Expand Up @@ -157,6 +158,7 @@ public void Init(Mediator mediator, PropertyTable propertyTable, XmlNode configu
Subscriber.Subscribe(EventConstants.SetToolFromName, SetToolFromName);
Subscriber.Subscribe(EventConstants.ReloadAreaTools, ReloadAreaTools);
Subscriber.Subscribe(EventConstants.GetContentControlParameters, GetContentControlParameters);
Subscriber.Subscribe(EventConstants.GetToolForList, GetToolForList);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I disagree with this type of request in this type of PR. This PR is a tool replacement.  If I understand this correctly, then I think this is a pre-existing coverage gap, not a gap introduced by this PR.  The mediator.SendMessage() call did not have this type of test coverage.

We probably should discuss as a group if tests for pre-existing coverage gaps that would be “nice to have”, should block a PR.

I’m adding the Claude generated tests to continue moving this PR forward.

}

private DateTime m_lastToolChange = DateTime.MinValue;
Expand Down Expand Up @@ -379,12 +381,11 @@ private bool FillListAreaList(UIListDisplayProperties display)
}

/// <summary>
/// This method is called BY REFLECTION through the mediator from LinkListener.FollowActiveLink, because the assembly dependencies
/// This method is called through the FwUtils Publisher/Subscriber from LinkListener.FollowActiveLink, because the assembly dependencies
/// are in the wrong direction. It finds the name of the tool we need to invoke to edit a given list.
/// The result is returned via the second element of the object array payload.
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
public bool OnGetToolForList(object parameters)
private void GetToolForList(object parameters)
{
var realParams = (object[]) parameters;
var list = (ICmPossibilityList)realParams[0];
Expand All @@ -409,12 +410,11 @@ public bool OnGetToolForList(object parameters)
if (possibleList == list)
{
realParams[1] = toolName;
return true;
return;
}
}
// If it's not a known list, try custom.
realParams[1] = GetCustomListToolName(list);
return true;
}

#region Custom List Methods
Expand Down
87 changes: 87 additions & 0 deletions Src/LexText/LexTextDll/LexTextDllTests/AreaListenerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
using NUnit.Framework;
using SIL.LCModel;
using SIL.LCModel.DomainServices;
using SIL.FieldWorks.Common.FwUtils;
using SIL.FieldWorks.XWorks.LexText;
using XCore;
using static SIL.FieldWorks.Common.FwUtils.FwUtils;

namespace LexTextDllTests
{
Expand Down Expand Up @@ -115,6 +117,35 @@ private static XmlNode SetupMinimalWindowConfig()
return fakeWindowConfig.DocumentElement;
}

/// <summary>
/// Builds a window configuration whose 'lists' area has a single tool wired, via its clerk's
/// recordList, to the possibility list identified by <paramref name="listGuid"/>.
/// </summary>
private static XmlNode SetupWindowConfigWithListTool(string clerkId, string toolValue, string listGuid)
{
var fakeWindowConfig = new XmlDocument();
fakeWindowConfig.LoadXml(
"<root>"
+ "<commands/>"
+ "<contextMenus/>"
+ "<item label=\"Lists\" value=\"lists\" icon=\"folder-lists\">"
+ "<parameters id=\"lists\">"
+ "<clerks>"
+ "<clerk id=\"" + clerkId + "\">"
+ "<recordList owner=\"unowned\" property=\"" + listGuid + "\"/>"
+ "</clerk>"
+ "</clerks>"
+ "<tools>"
+ "<tool value=\"" + toolValue + "\">"
+ "<control><parameters clerk=\"" + clerkId + "\"/></control>"
+ "</tool>"
+ "</tools>"
+ "</parameters>"
+ "</item>"
+ "</root>");
return fakeWindowConfig.DocumentElement;
}

#endregion

///--------------------------------------------------------------------------------------
Expand Down Expand Up @@ -161,5 +192,61 @@ public void AddListToXmlConfig()
var ccontextNodesAfter = node.SelectNodes(contextXPath).Count;
Assert.That(ccontextNodesAfter, Is.EqualTo(ccontextNodesBefore + 1), "Didn't add a context menu node.");
}

///--------------------------------------------------------------------------------------
/// <summary>
/// Publishing EventConstants.GetToolForList for a list that is wired into the window
/// configuration must return that tool's name via the second element of the payload array.
/// This exercises the full Pub/Sub path that LinkListener.FollowActiveLink relies on:
/// publish through the Publisher, the AreaListener subscriber handles it synchronously,
/// and the result comes back in parameters[1]. (LT-21515)
/// </summary>
///--------------------------------------------------------------------------------------
[Test]
public void GetToolForList_KnownList_ReturnsConfiguredToolName()
{
// Setup: a list wired to a configured tool via its clerk's recordList.
var ws = WritingSystemServices.kwsAnals;
var list = Cache.ServiceLocator.GetInstance<ICmPossibilityListFactory>().CreateUnowned("Some List", ws);
var windowConfig = SetupWindowConfigWithListTool("someListClerk", "myConfiguredListEdit", list.Guid.ToString());
m_propertyTable.SetProperty("WindowConfiguration", windowConfig, true);
m_propertyTable.SetPropertyPersistence("WindowConfiguration", false);

var parameters = new object[2];
parameters[0] = list;

// SUT: publish exactly as LinkListener.FollowActiveLink does.
Publisher.Publish(new PublisherParameterObject(EventConstants.GetToolForList, parameters));

// Verify: the configured tool name was returned via the payload.
Assert.That(parameters[1], Is.EqualTo("myConfiguredListEdit"));
}

///--------------------------------------------------------------------------------------
/// <summary>
/// Publishing EventConstants.GetToolForList for a list that is NOT in the configuration
/// must fall back to the generated custom-list tool name (the list name with whitespace
/// removed, plus "Edit"), returned via parameters[1]. (LT-21515)
/// </summary>
///--------------------------------------------------------------------------------------
[Test]
public void GetToolForList_UnknownList_ReturnsCustomToolName()
{
// Setup: a window configuration whose 'tools' section has no matching tool.
m_propertyTable.SetProperty("WindowConfiguration", SetupMinimalWindowConfig(), true);
m_propertyTable.SetPropertyPersistence("WindowConfiguration", false);

var ws = WritingSystemServices.kwsAnals;
var customList = Cache.ServiceLocator.GetInstance<ICmPossibilityListFactory>().CreateUnowned("My Custom List", ws);

var parameters = new object[2];
parameters[0] = customList;

// SUT
Publisher.Publish(new PublisherParameterObject(EventConstants.GetToolForList, parameters));

// Verify: whitespace stripped from the name, with "Edit" appended.
Assert.That(parameters[1], Is.EqualTo("MyCustomListEdit"));
}
}
}
6 changes: 2 additions & 4 deletions Src/xWorks/LinkListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -509,12 +509,10 @@ private bool FollowActiveLink(bool suspendLoadingRecord)
// Unfortunately AreaListener is in an assembly we can't reference.
// But there may be custom ones, so just listing them all here does not seem to be an option,
// and anyway it would be hard to maintain.
// Thus we've created this method (on AreaListener) which we call awkwardly throught the mediator.
// Thus we've created this method (on AreaListener) which we call through the FwUtils Publisher/Subscriber.
var parameters = new object[2];
parameters[0] = majorObject;
#pragma warning disable 618 // suppress obsolete warning
m_mediator.SendMessage("GetToolForList", parameters);
#pragma warning restore 618
Publisher.Publish(new PublisherParameterObject(EventConstants.GetToolForList, parameters));
realTool = (string)parameters[1];
break;
case RnResearchNbkTags.kClassId:
Expand Down
Loading