diff --git a/SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs b/SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs
new file mode 100644
index 0000000..e497077
--- /dev/null
+++ b/SharepointToolbox.Tests/Helpers/ExecuteQueryRetryHelperTests.cs
@@ -0,0 +1,33 @@
+using SharepointToolbox.Core.Helpers;
+
+namespace SharepointToolbox.Tests.Helpers;
+
+[Trait("Category", "Unit")]
+public class ExecuteQueryRetryHelperTests
+{
+ [Theory]
+ [InlineData("The request has been throttled -- 429")]
+ [InlineData("Service unavailable 503")]
+ [InlineData("SharePoint has throttled your request")]
+ public void IsThrottleException_ThrottleMessages_ReturnsTrue(string message)
+ {
+ var ex = new Exception(message);
+ Assert.True(ExecuteQueryRetryHelper.IsThrottleException(ex));
+ }
+
+ [Fact]
+ public void IsThrottleException_NonThrottleMessage_ReturnsFalse()
+ {
+ var ex = new Exception("File not found");
+ Assert.False(ExecuteQueryRetryHelper.IsThrottleException(ex));
+ }
+
+ [Fact]
+ public void IsThrottleException_NestedThrottleInInnerException_ReturnsFalse()
+ {
+ // Documents current behavior: only top-level Message is checked.
+ // Inner exceptions with "429" are NOT currently detected.
+ var ex = new Exception("outer", new Exception("429"));
+ Assert.False(ExecuteQueryRetryHelper.IsThrottleException(ex));
+ }
+}
diff --git a/SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs b/SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs
new file mode 100644
index 0000000..4a89ca0
--- /dev/null
+++ b/SharepointToolbox.Tests/Helpers/SharePointPaginationHelperTests.cs
@@ -0,0 +1,49 @@
+using SharepointToolbox.Core.Helpers;
+
+namespace SharepointToolbox.Tests.Helpers;
+
+[Trait("Category", "Unit")]
+public class SharePointPaginationHelperTests
+{
+ [Fact]
+ public void BuildPagedViewXml_NullInput_ReturnsViewWithRowLimit()
+ {
+ var result = SharePointPaginationHelper.BuildPagedViewXml(null, 2000);
+ Assert.Equal("2000", result);
+ }
+
+ [Fact]
+ public void BuildPagedViewXml_EmptyString_ReturnsViewWithRowLimit()
+ {
+ var result = SharePointPaginationHelper.BuildPagedViewXml("", 2000);
+ Assert.Equal("2000", result);
+ }
+
+ [Fact]
+ public void BuildPagedViewXml_WhitespaceOnly_ReturnsViewWithRowLimit()
+ {
+ var result = SharePointPaginationHelper.BuildPagedViewXml(" ", 2000);
+ Assert.Equal("2000", result);
+ }
+
+ [Fact]
+ public void BuildPagedViewXml_ExistingRowLimit_Replaces()
+ {
+ var input = "100";
+ var result = SharePointPaginationHelper.BuildPagedViewXml(input, 2000);
+ Assert.Equal("2000", result);
+ }
+
+ [Fact]
+ public void BuildPagedViewXml_NoRowLimit_AppendsBeforeClosingView()
+ {
+ var input = "";
+ var result = SharePointPaginationHelper.BuildPagedViewXml(input, 2000);
+ Assert.Contains("2000", result);
+ Assert.EndsWith("", result);
+ // Ensure RowLimit is inserted before the closing
+ var rowLimitIndex = result.IndexOf("2000", StringComparison.Ordinal);
+ var closingViewIndex = result.LastIndexOf("", StringComparison.Ordinal);
+ Assert.True(rowLimitIndex < closingViewIndex, "RowLimit should appear before ");
+ }
+}
diff --git a/SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs b/SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs
index 7b353e5..76e2c84 100644
--- a/SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs
+++ b/SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs
@@ -36,7 +36,7 @@ public static class ExecuteQueryRetryHelper
}
}
- private static bool IsThrottleException(Exception ex)
+ internal static bool IsThrottleException(Exception ex)
{
var msg = ex.Message;
return msg.Contains("429") || msg.Contains("503") ||
diff --git a/SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs b/SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs
index 151634e..732f213 100644
--- a/SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs
+++ b/SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs
@@ -36,7 +36,7 @@ public static class SharePointPaginationHelper
while (query.ListItemCollectionPosition != null);
}
- private static string BuildPagedViewXml(string? existingXml, int rowLimit)
+ internal static string BuildPagedViewXml(string? existingXml, int rowLimit)
{
// Inject or replace RowLimit in existing CAML, or create minimal view
if (string.IsNullOrWhiteSpace(existingXml))