From 7567c6dec6821b3bf022e88ba2305ef684f7dbf0 Mon Sep 17 00:00:00 2001 From: "Arooshi Avasthy (from Dev Box)" Date: Tue, 25 Nov 2025 12:09:14 -0800 Subject: [PATCH] Add tests for full text policy. --- .../Fluent/ContainerSettingsTests.cs | 102 +++++++++++++++++- .../ContainerDefinitionForCreateTests.cs | 79 ++++++++++++++ .../SettingsContractTests.cs | 68 +++++++++++- 3 files changed, 245 insertions(+), 4 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs index 16186a5835..e48b2f440c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs @@ -3,7 +3,7 @@ //------------------------------------------------------------ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests -{ +{ using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using System; @@ -1304,8 +1304,104 @@ public async Task WithClientEncryptionPolicyFailureTest() { Assert.IsTrue(ex.Message.Contains("Only Deterministic encryption type is supported for path: /id."), ex.Message); } - } - + } + + [Ignore("Marking as ignore until emulator is updated")] + [TestMethod] + [DataRow("en-US")] + [DataRow("fr-FR")] + [DataRow("de-DE")] + [DataRow("it-IT")] + [DataRow("pt-BR")] + [DataRow("pt-PT")] + [DataRow("es-ES")] + public async Task TestFullTextSearchPolicyWithAllSupportedDefaultLanguages(string defaultLanguage) + { + string fullTextPath1 = "/fts1", fullTextPath2 = "/fts2"; + string endpoint = ""; + string key = ""; + + string databaseName = "TestDatabaseFullTextPolicy"; + string containerName = "TestContainerFullTextPolicy_"+ defaultLanguage; + + CosmosClientOptions clientOptions = new CosmosClientOptions + { + ConnectionMode = ConnectionMode.Direct, + }; + CosmosClient client = new(endpoint, key, clientOptions); + + Database databaseForFullTextSearch = await client.CreateDatabaseIfNotExistsAsync(databaseName); + try + { + string partitionKeyPath = "/pk"; + + Collection fullTextPaths = new Collection() + { + new FullTextPath() + { + Path = fullTextPath1, + Language = defaultLanguage, + }, + new FullTextPath() + { + Path = fullTextPath2, + Language = defaultLanguage, + } + }; + + ContainerResponse containerResponse = + await databaseForFullTextSearch.DefineContainer(containerName, partitionKeyPath) + .WithFullTextPolicy( + defaultLanguage: defaultLanguage, + fullTextPaths: fullTextPaths) + .Attach() + .WithIndexingPolicy() + .WithFullTextIndex() + .Path(fullTextPath1) + .Attach() + .WithFullTextIndex() + .Path(fullTextPath2) + .Attach() + .Attach() + .CreateAsync(); + + Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode, + $"Failed to create container with default language: {defaultLanguage}"); + Assert.AreEqual(containerName, containerResponse.Resource.Id); + Assert.AreEqual(partitionKeyPath, containerResponse.Resource.PartitionKey.Paths.First()); + + ContainerProperties containerSettings = containerResponse.Resource; + + // Validate FullText Policy + Assert.IsNotNull(containerSettings.FullTextPolicy, + $"FullTextPolicy is null for language: {defaultLanguage}"); + Assert.AreEqual(defaultLanguage, containerSettings.FullTextPolicy.DefaultLanguage, + $"DefaultLanguage mismatch for: {defaultLanguage}"); + Assert.IsNotNull(containerSettings.FullTextPolicy.FullTextPaths); + Assert.AreEqual(fullTextPaths.Count, containerSettings.FullTextPolicy.FullTextPaths.Count()); + + // Validate each path has the correct language + foreach (FullTextPath path in containerSettings.FullTextPolicy.FullTextPaths) + { + Assert.AreEqual(defaultLanguage, path.Language, + $"Path language mismatch for default language: {defaultLanguage}"); + } + + // Validate Full Text Indexes + Assert.IsNotNull(containerSettings.IndexingPolicy.FullTextIndexes); + Assert.AreEqual(fullTextPaths.Count, containerSettings.IndexingPolicy.FullTextIndexes.Count()); + Assert.AreEqual(fullTextPath1, containerSettings.IndexingPolicy.FullTextIndexes[0].Path); + Assert.AreEqual(fullTextPath2, containerSettings.IndexingPolicy.FullTextIndexes[1].Path); + + // Clean up container after test + await containerResponse.Container.DeleteContainerAsync(); + } + finally + { + await databaseForFullTextSearch.DeleteAsync(); + } + } + private bool VerifyClientEncryptionIncludedPath(ClientEncryptionIncludedPath expected, ClientEncryptionIncludedPath actual) { return expected.Path == actual.Path && diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs index 7d4c20cc71..98562625ef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs @@ -574,6 +574,85 @@ public async Task ValidateVectorEmbeddingsAndIndexingPolicyUsingContainerBuilder It.IsAny(), It.IsAny()), Times.Once); } + + [TestMethod] + [DataRow("en-US")] + [DataRow("fr-FR")] + [DataRow("de-DE")] + [DataRow("it-IT")] + [DataRow("pt-BR")] + [DataRow("pt-PT")] + [DataRow("es-ES")] + public async Task ValidateFullTextPolicyWithAllSupportedLanguages(string language) + { + string fullTextPath1 = "/fts1", fullTextPath2 = "/fts2"; + + Collection fullTextPaths = new Collection() + { + new Cosmos.FullTextPath() + { + Path = fullTextPath1, + Language = language, + }, + new Cosmos.FullTextPath() + { + Path = fullTextPath2, + Language = language, + } + }; + + Mock mockContainerResponse = new Mock(); + mockContainerResponse + .Setup(x => x.StatusCode) + .Returns(HttpStatusCode.Created); + + Mock mockDatabase = new Mock(); + Mock mockClient = new Mock(); + mockDatabase.Setup(m => m.Client).Returns(mockClient.Object); + mockDatabase + .Setup(c => c.CreateContainerAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(mockContainerResponse.Object); + mockDatabase + .Setup(c => c.Id) + .Returns(Guid.NewGuid().ToString()); + + ContainerBuilder containerFluentDefinition = new ContainerBuilder( + mockDatabase.Object, + containerName, + partitionKey); + + ContainerResponse response = await containerFluentDefinition + .WithFullTextPolicy( + defaultLanguage: language, + fullTextPaths: fullTextPaths) + .Attach() + .WithIndexingPolicy() + .WithFullTextIndex() + .Path(fullTextPath1) + .Attach() + .WithFullTextIndex() + .Path(fullTextPath2) + .Attach() + .Attach() + .CreateAsync(); + + Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); + + // Verify the correct language was passed + mockDatabase.Verify(c => c.CreateContainerAsync( + It.Is((settings) => + settings.FullTextPolicy.DefaultLanguage == language && + settings.FullTextPolicy.FullTextPaths.Count == 2 && + settings.FullTextPolicy.FullTextPaths.All(p => p.Language == language)), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once, + $"Failed to verify container creation with language: {language}"); + } private static CosmosClientContext GetContext() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs index 8b38041ee1..0e023740e1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs @@ -18,7 +18,8 @@ namespace Microsoft.Azure.Cosmos.Tests using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; - using FullTextPath = Microsoft.Azure.Cosmos.FullTextPath; + using FullTextPath = Microsoft.Azure.Cosmos.FullTextPath; + using FullTextPolicy = Microsoft.Azure.Cosmos.FullTextPolicy; [TestClass] public class SettingsContractTests @@ -1203,6 +1204,71 @@ public void FullTextPolicySerialization() Assert.AreEqual(JTokenType.String, fullTextLanguageDeSerialized.Type, "Full Text Policy serialized language should be a string."); Assert.IsTrue(fullTextPath1.Equals(fullTextPathsDeSerialized.Value()[0].ToObject())); Assert.IsTrue(fullTextPath2.Equals(fullTextPathsDeSerialized.Value()[1].ToObject())); + } + + [TestMethod] + [DataRow("en-US")] + [DataRow("fr-FR")] + [DataRow("de-DE")] + [DataRow("it-IT")] + [DataRow("pt-BR")] + [DataRow("pt-PT")] + [DataRow("es-ES")] + public void FullTextPolicySerializationWithAllSupportedLanguages(string language) + { + FullTextPolicy fullTextPolicy = new FullTextPolicy + { + DefaultLanguage = language, + FullTextPaths = new Collection + { + new FullTextPath { Path = "/text1", Language = language }, + new FullTextPath { Path = "/text2", Language = "en-US" }, + new FullTextPath { Path = "/text3" } // No language specified, should use default + } + }; + + string serialized = CosmosSerialize(fullTextPolicy); + Assert.IsNotNull(serialized); + Assert.IsTrue(serialized.Contains($"\"defaultLanguage\":\"{language}\""), + $"Serialized JSON should contain defaultLanguage: {language}"); + + FullTextPolicy deserialized = CosmosDeserialize(serialized); + Assert.IsNotNull(deserialized); + Assert.AreEqual(language, deserialized.DefaultLanguage, + $"DefaultLanguage mismatch after deserialization for: {language}"); + Assert.AreEqual(3, deserialized.FullTextPaths.Count); + Assert.AreEqual(language, deserialized.FullTextPaths[0].Language); + Assert.AreEqual("en-US", deserialized.FullTextPaths[1].Language); + Assert.IsNull(deserialized.FullTextPaths[2].Language); + } + + [TestMethod] + [DataRow("en-US")] + [DataRow("fr-FR")] + [DataRow("de-DE")] + [DataRow("it-IT")] + [DataRow("ja-JP")] + [DataRow("pt-BR")] + [DataRow("pt-PT")] + [DataRow("es-ES")] + public void FullTextPathSerializationWithAllLanguages(string language) + { + FullTextPath fullTextPath = new FullTextPath + { + Path = "/testPath", + Language = language + }; + + string serialized = CosmosSerialize(fullTextPath); + Assert.IsNotNull(serialized); + Assert.IsTrue(serialized.Contains($"\"language\":\"{language}\""), + $"Serialized JSON should contain language: {language}"); + + FullTextPath deserialized = CosmosDeserialize(serialized); + Assert.IsNotNull(deserialized); + Assert.AreEqual("/testPath", deserialized.Path); + Assert.AreEqual(language, deserialized.Language, + $"Language mismatch after deserialization for: {language}"); } private static T CosmosDeserialize(string payload)