diff --git a/src/Constructorio_NET.Tests/client/modules/AutocompleteTests.cs b/src/Constructorio_NET.Tests/client/modules/AutocompleteTests.cs index ca58dd96..e8edd593 100644 --- a/src/Constructorio_NET.Tests/client/modules/AutocompleteTests.cs +++ b/src/Constructorio_NET.Tests/client/modules/AutocompleteTests.cs @@ -203,7 +203,7 @@ public async Task GetAutocompleteResultsShouldReturnResultWithHiddenFields() AutocompleteRequest req = new AutocompleteRequest("item1") { UserInfo = UserInfo, - HiddenFields = new List { "testField" } + FmtOptions = new FmtOptions { HiddenFields = new List { "testField" } } }; ConstructorIO constructorio = new ConstructorIO(this.Config); AutocompleteResponse res = await constructorio.Autocomplete.GetAutocompleteResults(req); diff --git a/src/Constructorio_NET.Tests/client/modules/BrowseTests.cs b/src/Constructorio_NET.Tests/client/modules/BrowseTests.cs index 98f27c45..47067fde 100644 --- a/src/Constructorio_NET.Tests/client/modules/BrowseTests.cs +++ b/src/Constructorio_NET.Tests/client/modules/BrowseTests.cs @@ -589,7 +589,7 @@ public async Task GetBrowseResultsShouldReturnResultWithHiddenFields() BrowseRequest req = new BrowseRequest(this.FilterName, this.FilterValue) { UserInfo = this.UserInfo, - HiddenFields = new List { requestedHiddenField } + FmtOptions = new FmtOptions { HiddenFields = new List { requestedHiddenField } } }; ConstructorIO constructorio = new ConstructorIO(this.Config); BrowseResponse res = await constructorio.Browse.GetBrowseResults(req); @@ -606,7 +606,7 @@ public async Task GetBrowseResultsShouldReturnResultWithHiddenFacets() BrowseRequest req = new BrowseRequest(this.FilterName, this.FilterValue) { UserInfo = this.UserInfo, - HiddenFacets = new List { requestedHiddenFacet } + FmtOptions = new FmtOptions { HiddenFacets = new List { requestedHiddenFacet } } }; ConstructorIO constructorio = new ConstructorIO(this.Config); BrowseResponse res = await constructorio.Browse.GetBrowseResults(req); @@ -865,6 +865,23 @@ public async Task GetBrowseItemsResultsWithResultParams() Assert.IsNotNull(res.ResultId, "ResultId should exist"); } + [Test] + public async Task GetBrowseItemsResultsShouldReturnResultWithHiddenFields() + { + string requestedHiddenField = "testField"; + BrowseItemsRequest req = new BrowseItemsRequest(this.ItemIds) + { + UserInfo = this.UserInfo, + FmtOptions = new FmtOptions { HiddenFields = new List { requestedHiddenField } } + }; + ConstructorIO constructorio = new ConstructorIO(this.Config); + BrowseResponse res = await constructorio.Browse.GetBrowseItemsResult(req); + var returnedHiddenField = res.Response.Results[0].Data.Metadata[requestedHiddenField]; + + Assert.NotNull(res.ResultId, "Result id exists"); + Assert.NotNull(returnedHiddenField, "Hidden field returned"); + } + [Test] public async Task GetBrowseFacetsResults() { @@ -913,8 +930,7 @@ public async Task GetBrowseFacetsWithFmtOptionParams() BrowseFacetsRequest req = new BrowseFacetsRequest { UserInfo = this.UserInfo, - ShowHiddenFacets = true, - ShowProtectedFacets = true + FmtOptions = new FmtOptions { ShowHiddenFacets = true, ShowProtectedFacets = true } }; ConstructorIO constructorio = new ConstructorIO(this.Config); BrowseFacetsResponse res = await constructorio.Browse.GetBrowseFacetsResult(req); @@ -956,8 +972,7 @@ public async Task GetBrowseFacetOptionsWithFmtOptionParams() BrowseFacetOptionsRequest req = new BrowseFacetOptionsRequest(this.FilterName) { UserInfo = this.UserInfo, - ShowHiddenFacets = true, - ShowProtectedFacets = true + FmtOptions = new FmtOptions { ShowHiddenFacets = true, ShowProtectedFacets = true } }; ConstructorIO constructorio = new ConstructorIO(this.Config); BrowseFacetOptionsResponse res = await constructorio.Browse.GetBrowseFacetOptionsResult( diff --git a/src/Constructorio_NET.Tests/client/modules/RecommendationsTests.cs b/src/Constructorio_NET.Tests/client/modules/RecommendationsTests.cs index 09b30e3d..d9edef37 100644 --- a/src/Constructorio_NET.Tests/client/modules/RecommendationsTests.cs +++ b/src/Constructorio_NET.Tests/client/modules/RecommendationsTests.cs @@ -339,6 +339,37 @@ public async Task GetRecommendationsResultsWithPreFilterExpression() Assert.IsNotNull(res.Request["pre_filter_expression"], "PreFilterExpression was passed as parameter"); } + [Test] + public async Task GetRecommendationsResultsShouldReturnResultWithHiddenFields() + { + string requestedHiddenField = "testField"; + RecommendationsRequest req = new RecommendationsRequest("filtered_items") + { + UserInfo = this.UserInfo, + Filters = new Dictionary>() + { + { "Brand", new List() { "XYZ" } } + }, + FmtOptions = new FmtOptions { HiddenFields = new List { requestedHiddenField } } + }; + ConstructorIO constructorio = new ConstructorIO(this.Config); + RecommendationsResponse res = await constructorio.Recommendations.GetRecommendationsResults(req); + + Assert.NotNull(res.ResultId, "Result id exists"); + Assert.Greater(res.Response.Results.Count, 0, "Results expected to be greater than 0"); + + var metadata = res.Response.Results[0].Data?.Metadata; + Assert.IsNotNull(metadata, "Result metadata exists"); + Assert.IsTrue( + metadata.ContainsKey(requestedHiddenField), + "Requested hidden field is present in result metadata" + ); + Assert.IsNotNull( + metadata[requestedHiddenField], + "Requested hidden field has a non-null value in result metadata" + ); + } + [Test] public async Task GetRecommendationsResultsWithPreFilterExpressionJson() { diff --git a/src/Constructorio_NET.Tests/client/modules/SearchTests.cs b/src/Constructorio_NET.Tests/client/modules/SearchTests.cs index 146d6252..d0c553df 100644 --- a/src/Constructorio_NET.Tests/client/modules/SearchTests.cs +++ b/src/Constructorio_NET.Tests/client/modules/SearchTests.cs @@ -73,9 +73,11 @@ public async Task GetSearchResultsShouldReturnResultWithVaritionsSlice() SearchRequest req = new SearchRequest("item1") { UserInfo = this.UserInfo }; ConstructorIO constructorio = new ConstructorIO(this.Config); SearchResponse res = await constructorio.Search.GetSearchResults(req); - string sliceAttribute = res.Response.Results[0].VariationSlice["Color"][0]; - Assert.AreEqual("Blue", sliceAttribute); + Assert.IsNotNull(res.Response.Results[0].VariationSlice, "VariationSlice should exist"); + Assert.IsTrue(res.Response.Results[0].VariationSlice.ContainsKey("Color"), "VariationSlice should contain Color key"); + Assert.Greater(res.Response.Results[0].VariationSlice["Color"].Count, 0, "Color slice should have at least one value"); + Assert.IsNotEmpty(res.Response.Results[0].VariationSlice["Color"][0], "Color slice value should not be empty"); } [Test] @@ -678,7 +680,7 @@ public async Task GetSearchResultsShouldReturnResultWithHiddenFields() SearchRequest req = new SearchRequest("item1") { UserInfo = this.UserInfo, - HiddenFields = new List { requestedHiddenField } + FmtOptions = new FmtOptions { HiddenFields = new List { requestedHiddenField } } }; ConstructorIO constructorio = new ConstructorIO(this.Config); SearchResponse res = await constructorio.Search.GetSearchResults(req); @@ -695,7 +697,7 @@ public async Task GetSearchResultsShouldReturnResultWithHiddenFacets() SearchRequest req = new SearchRequest("item1") { UserInfo = this.UserInfo, - HiddenFacets = new List { requestedHiddenFacet } + FmtOptions = new FmtOptions { HiddenFacets = new List { requestedHiddenFacet } } }; ConstructorIO constructorio = new ConstructorIO(this.Config); SearchResponse res = await constructorio.Search.GetSearchResults(req); diff --git a/src/Constructorio_NET.Tests/models/Browse/BrowseFacetOptionsRequestTest.cs b/src/Constructorio_NET.Tests/models/Browse/BrowseFacetOptionsRequestTest.cs index 73d78503..6caa5096 100644 --- a/src/Constructorio_NET.Tests/models/Browse/BrowseFacetOptionsRequestTest.cs +++ b/src/Constructorio_NET.Tests/models/Browse/BrowseFacetOptionsRequestTest.cs @@ -37,6 +37,66 @@ public void GetRequestParameters() Assert.AreEqual(this.FilterName, requestParameters[Constants.FACET_NAME]); } + [Test] + public void GetRequestParametersWithShowHiddenFacets() + { + BrowseFacetOptionsRequest req = new BrowseFacetOptionsRequest(FilterName) + { + FmtOptions = new FmtOptions { ShowHiddenFacets = true }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + } + + [Test] + public void GetRequestParametersWithShowProtectedFacets() + { + BrowseFacetOptionsRequest req = new BrowseFacetOptionsRequest(FilterName) + { + FmtOptions = new FmtOptions { ShowProtectedFacets = true }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]"]); + } + + [Test] + public void GetRequestParametersWithFmtOptions() + { + BrowseFacetOptionsRequest req = new BrowseFacetOptionsRequest(FilterName) + { + FmtOptions = new FmtOptions() + { + GroupsMaxDepth = 3, + ShowHiddenFacets = true, + ShowProtectedFacets = true, + }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("3", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]"]); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]"]); + } + + [Test] + public void GetRequestParametersWithFmtOptionsAndShowHiddenFacets() + { + BrowseFacetOptionsRequest req = new BrowseFacetOptionsRequest(FilterName) + { + FmtOptions = new FmtOptions() + { + GroupsMaxDepth = 3, + ShowHiddenFacets = true, + }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("3", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]"]); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + } + [Test] public void GetRequestHeaders() { diff --git a/src/Constructorio_NET.Tests/models/Browse/BrowseFacetsRequestTest.cs b/src/Constructorio_NET.Tests/models/Browse/BrowseFacetsRequestTest.cs index 5eb0ec0e..774456e1 100644 --- a/src/Constructorio_NET.Tests/models/Browse/BrowseFacetsRequestTest.cs +++ b/src/Constructorio_NET.Tests/models/Browse/BrowseFacetsRequestTest.cs @@ -44,6 +44,66 @@ public void GetRequestParameters() Assert.AreEqual(this.Offset, requestParameters[Constants.OFFSET]); } + [Test] + public void GetRequestParametersWithShowHiddenFacets() + { + BrowseFacetsRequest req = new BrowseFacetsRequest() + { + FmtOptions = new FmtOptions { ShowHiddenFacets = true }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + } + + [Test] + public void GetRequestParametersWithShowProtectedFacets() + { + BrowseFacetsRequest req = new BrowseFacetsRequest() + { + FmtOptions = new FmtOptions { ShowProtectedFacets = true }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]"]); + } + + [Test] + public void GetRequestParametersWithFmtOptions() + { + BrowseFacetsRequest req = new BrowseFacetsRequest() + { + FmtOptions = new FmtOptions() + { + GroupsMaxDepth = 3, + ShowHiddenFacets = true, + ShowProtectedFacets = true, + }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("3", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]"]); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]"]); + } + + [Test] + public void GetRequestParametersWithFmtOptionsAndShowHiddenFacets() + { + BrowseFacetsRequest req = new BrowseFacetsRequest() + { + FmtOptions = new FmtOptions() + { + GroupsMaxDepth = 3, + ShowHiddenFacets = true, + }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + Assert.AreEqual("3", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]"]); + Assert.AreEqual("true", requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + } + [Test] public void GetRequestHeaders() { diff --git a/src/Constructorio_NET.Tests/models/Recommendations/RecommendationsRequestTest.cs b/src/Constructorio_NET.Tests/models/Recommendations/RecommendationsRequestTest.cs index af55362d..f7e532e2 100644 --- a/src/Constructorio_NET.Tests/models/Recommendations/RecommendationsRequestTest.cs +++ b/src/Constructorio_NET.Tests/models/Recommendations/RecommendationsRequestTest.cs @@ -86,6 +86,23 @@ public void GetRequestParametersWithVariationIds() Assert.AreEqual(this.VariationIds, requestParameters["variation_id"]); } + [Test] + public void GetRequestParametersWithFmtOptions() + { + RecommendationsRequest req = new RecommendationsRequest(this.Pod) + { + UserInfo = this.UserInfo, + FmtOptions = new FmtOptions + { + HiddenFields = new List { "inventory" }, + }, + }; + + Hashtable requestParameters = req.GetRequestParameters(); + List hiddenFields = (List)requestParameters[$"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FIELDS}]"]; + Assert.AreEqual(new List { "inventory" }, hiddenFields); + } + [Test] public void RecommendationsRequestWithInvalidPod() { diff --git a/src/Constructorio_NET.Tests/models/common/FmtOptionsTest.cs b/src/Constructorio_NET.Tests/models/common/FmtOptionsTest.cs new file mode 100644 index 00000000..5f71d1f0 --- /dev/null +++ b/src/Constructorio_NET.Tests/models/common/FmtOptionsTest.cs @@ -0,0 +1,160 @@ +using System.Collections; +using System.Collections.Generic; +using Constructorio_NET.Models; +using Constructorio_NET.Utils; +using NUnit.Framework; + +namespace Constructorio_NET.Tests +{ + [TestFixture] + public class FmtOptionsTest + { + [Test] + public void GetQueryParametersEmpty() + { + FmtOptions fmtOptions = new FmtOptions(); + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual(0, result.Count); + } + + [Test] + public void GetQueryParametersGroupsMaxDepth() + { + FmtOptions fmtOptions = new FmtOptions { GroupsMaxDepth = 3 }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("3", result[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersGroupsStart() + { + FmtOptions fmtOptions = new FmtOptions { GroupsStart = "current" }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("current", result[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_START}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersShowHiddenFields() + { + FmtOptions fmtOptions = new FmtOptions { ShowHiddenFields = true }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("true", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FIELDS}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersShowHiddenFieldsFalse() + { + FmtOptions fmtOptions = new FmtOptions { ShowHiddenFields = false }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("false", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FIELDS}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersVariationsReturnType() + { + FmtOptions fmtOptions = new FmtOptions { VariationsReturnType = "all" }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("all", result[$"{Constants.FMT_OPTIONS}[{Constants.VARIATIONS_RETURN_TYPE}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersShowHiddenFacets() + { + FmtOptions fmtOptions = new FmtOptions { ShowHiddenFacets = true }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("true", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersShowHiddenFacetsFalse() + { + FmtOptions fmtOptions = new FmtOptions { ShowHiddenFacets = false }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("false", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersShowProtectedFacets() + { + FmtOptions fmtOptions = new FmtOptions { ShowProtectedFacets = true }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("true", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersShowProtectedFacetsFalse() + { + FmtOptions fmtOptions = new FmtOptions { ShowProtectedFacets = false }; + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual("false", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]"]); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersFields() + { + FmtOptions fmtOptions = new FmtOptions { Fields = new List { "id", "name" } }; + Hashtable result = fmtOptions.GetQueryParameters(); + List fields = (List)result[$"{Constants.FMT_OPTIONS}[{Constants.FIELDS}]"]; + Assert.AreEqual(new List { "id", "name" }, fields); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersHiddenFields() + { + FmtOptions fmtOptions = new FmtOptions { HiddenFields = new List { "inventory", "margin" } }; + Hashtable result = fmtOptions.GetQueryParameters(); + List hiddenFields = (List)result[$"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FIELDS}]"]; + Assert.AreEqual(new List { "inventory", "margin" }, hiddenFields); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersHiddenFacets() + { + FmtOptions fmtOptions = new FmtOptions { HiddenFacets = new List { "brand", "category" } }; + Hashtable result = fmtOptions.GetQueryParameters(); + List hiddenFacets = (List)result[$"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FACETS}]"]; + Assert.AreEqual(new List { "brand", "category" }, hiddenFacets); + Assert.AreEqual(1, result.Count); + } + + [Test] + public void GetQueryParametersAllProperties() + { + FmtOptions fmtOptions = new FmtOptions + { + GroupsMaxDepth = 5, + GroupsStart = "top", + ShowHiddenFields = true, + VariationsReturnType = "all", + ShowHiddenFacets = true, + ShowProtectedFacets = false, + Fields = new List { "id" }, + HiddenFields = new List { "inventory" }, + HiddenFacets = new List { "brand" }, + }; + + Hashtable result = fmtOptions.GetQueryParameters(); + Assert.AreEqual(9, result.Count); + Assert.AreEqual("5", result[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]"]); + Assert.AreEqual("top", result[$"{Constants.FMT_OPTIONS}[{Constants.GROUPS_START}]"]); + Assert.AreEqual("true", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FIELDS}]"]); + Assert.AreEqual("all", result[$"{Constants.FMT_OPTIONS}[{Constants.VARIATIONS_RETURN_TYPE}]"]); + Assert.AreEqual("true", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]"]); + Assert.AreEqual("false", result[$"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]"]); + Assert.AreEqual(new List { "id" }, result[$"{Constants.FMT_OPTIONS}[{Constants.FIELDS}]"]); + Assert.AreEqual(new List { "inventory" }, result[$"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FIELDS}]"]); + Assert.AreEqual(new List { "brand" }, result[$"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FACETS}]"]); + } + } +} diff --git a/src/Constructorio_NET.Tests/utils/HelpersTest.cs b/src/Constructorio_NET.Tests/utils/HelpersTest.cs index ba3ea796..ab05ef12 100644 --- a/src/Constructorio_NET.Tests/utils/HelpersTest.cs +++ b/src/Constructorio_NET.Tests/utils/HelpersTest.cs @@ -166,7 +166,7 @@ public void MakeUrlSearchWithHiddenFields() List hiddenFields = new List() { "inventory", "margin" }; Hashtable queryParams = new Hashtable() { - { Constants.HIDDEN_FIELDS, hiddenFields } + { $"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FIELDS}]", hiddenFields } }; string url = MakeUrl(this.Options, paths, queryParams); @@ -182,7 +182,7 @@ public void MakeUrlSearchWithHiddenFacets() List hiddenFacets = new List() { "inventory", "margin" }; Hashtable queryParams = new Hashtable() { - { Constants.HIDDEN_FACETS, hiddenFacets } + { $"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FACETS}]", hiddenFacets } }; string url = MakeUrl(this.Options, paths, queryParams); @@ -195,15 +195,11 @@ public void MakeUrlSearchWithHiddenFacets() public void MakeUrlSearchWithFmtOptions() { List paths = new List { "search", this.Query }; - Dictionary fmtOptions = new Dictionary() - { - { "groups_max_depth", "3" }, - { "groups_start", "current" } - }; Hashtable queryParams = new Hashtable() { { Constants.SECTION, "Search Suggestions" }, - { Constants.FMT_OPTIONS, fmtOptions } + { $"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]", "3" }, + { $"{Constants.FMT_OPTIONS}[{Constants.GROUPS_START}]", "current" }, }; string url = MakeUrl(this.Options, paths, queryParams); @@ -214,6 +210,77 @@ public void MakeUrlSearchWithFmtOptions() Assert.That(regexMatched1 && regexMatched2, "url should be properly formed"); } + [Test] + public void MakeUrlSearchWithFmtOptionsFieldsArray() + { + List paths = new List { "search", this.Query }; + Hashtable queryParams = new Hashtable() + { + { $"{Constants.FMT_OPTIONS}[{Constants.FIELDS}]", new List { "id", "variation_id", "name" } } + }; + + string url = MakeUrl(this.Options, paths, queryParams); + bool hasField0 = Regex.Match(url, "&fmt_options%5Bfields%5D=id").Success; + bool hasField1 = Regex.Match(url, "&fmt_options%5Bfields%5D=variation_id").Success; + bool hasField2 = Regex.Match(url, "&fmt_options%5Bfields%5D=name").Success; + Assert.That(hasField0 && hasField1 && hasField2, "url should have repeated fields keys"); + } + + [Test] + public void MakeUrlSearchWithFmtOptionsHiddenFieldsArray() + { + List paths = new List { "search", this.Query }; + Hashtable queryParams = new Hashtable() + { + { $"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FIELDS}]", new List { "inventory", "margin" } } + }; + + string url = MakeUrl(this.Options, paths, queryParams); + bool hasField0 = Regex.Match(url, "&fmt_options%5Bhidden_fields%5D=inventory").Success; + bool hasField1 = Regex.Match(url, "&fmt_options%5Bhidden_fields%5D=margin").Success; + Assert.That(hasField0 && hasField1, "url should have repeated hidden_fields keys"); + } + + [Test] + public void MakeUrlSearchWithFmtOptionsHiddenFacetsArray() + { + List paths = new List { "search", this.Query }; + Hashtable queryParams = new Hashtable() + { + { $"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FACETS}]", new List { "brand", "category" } } + }; + + string url = MakeUrl(this.Options, paths, queryParams); + bool hasFacet0 = Regex.Match(url, "&fmt_options%5Bhidden_facets%5D=brand").Success; + bool hasFacet1 = Regex.Match(url, "&fmt_options%5Bhidden_facets%5D=category").Success; + Assert.That(hasFacet0 && hasFacet1, "url should have repeated hidden_facets keys"); + } + + [Test] + public void MakeUrlSearchWithFmtOptionsAllProperties() + { + List paths = new List { "search", this.Query }; + Hashtable queryParams = new Hashtable() + { + { $"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]", "5" }, + { $"{Constants.FMT_OPTIONS}[{Constants.GROUPS_START}]", "top" }, + { $"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FIELDS}]", "true" }, + { $"{Constants.FMT_OPTIONS}[{Constants.VARIATIONS_RETURN_TYPE}]", "all" }, + { $"{Constants.FMT_OPTIONS}[{Constants.FIELDS}]", new List { "id" } }, + { $"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FIELDS}]", new List { "inventory" } }, + { $"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FACETS}]", new List { "brand" } }, + }; + + string url = MakeUrl(this.Options, paths, queryParams); + Assert.That(Regex.Match(url, "&fmt_options%5Bgroups_max_depth%5D=5").Success, "should have groups_max_depth"); + Assert.That(Regex.Match(url, "&fmt_options%5Bgroups_start%5D=top").Success, "should have groups_start"); + Assert.That(Regex.Match(url, "&fmt_options%5Bshow_hidden_fields%5D=true").Success, "should have show_hidden_fields"); + Assert.That(Regex.Match(url, "&fmt_options%5Bvariations_return_type%5D=all").Success, "should have variations_return_type"); + Assert.That(Regex.Match(url, "&fmt_options%5Bfields%5D=id").Success, "should have fields array"); + Assert.That(Regex.Match(url, "&fmt_options%5Bhidden_fields%5D=inventory").Success, "should have hidden_fields array"); + Assert.That(Regex.Match(url, "&fmt_options%5Bhidden_facets%5D=brand").Success, "should have hidden_facets array"); + } + [Test] public void MakeUrlSearchWithFiltersPerSection() { diff --git a/src/constructor.io/models/Autocomplete/AutocompleteRequest.cs b/src/constructor.io/models/Autocomplete/AutocompleteRequest.cs index fb5ce35a..a10f00f9 100644 --- a/src/constructor.io/models/Autocomplete/AutocompleteRequest.cs +++ b/src/constructor.io/models/Autocomplete/AutocompleteRequest.cs @@ -32,9 +32,9 @@ public class AutocompleteRequest : IFilterable, IUserDetails public Dictionary>> FiltersPerSection { get; set; } /// - /// Gets or sets hidden metadata fields to return. + /// Gets or sets the format options used to refine result groups. /// - public List HiddenFields { get; set; } + public FmtOptions FmtOptions { get; set; } /// /// Gets or sets user test cells. @@ -126,9 +126,12 @@ public Hashtable GetRequestParameters() } } - if (this.HiddenFields != null) + if (this.FmtOptions != null) { - parameters.Add(Constants.HIDDEN_FIELDS, this.HiddenFields); + foreach (DictionaryEntry entry in this.FmtOptions.GetQueryParameters()) + { + parameters.Add(entry.Key, entry.Value); + } } return parameters; diff --git a/src/constructor.io/models/Browse/BrowseFacetOptionsRequest.cs b/src/constructor.io/models/Browse/BrowseFacetOptionsRequest.cs index b4bc0cae..7e809d9d 100644 --- a/src/constructor.io/models/Browse/BrowseFacetOptionsRequest.cs +++ b/src/constructor.io/models/Browse/BrowseFacetOptionsRequest.cs @@ -11,10 +11,8 @@ namespace Constructorio_NET.Models public class BrowseFacetOptionsRequest { public string FacetName { get; set; } - public bool ShowHiddenFacets { get; set; } - public bool ShowProtectedFacets { get; set; } + public FmtOptions FmtOptions { get; set; } public UserInfo UserInfo { get; set; } - private Dictionary FmtOptions { get; set; } /// /// Initializes a new instance of the class. @@ -22,7 +20,6 @@ public class BrowseFacetOptionsRequest /// Facet to use for the request. public BrowseFacetOptionsRequest(string facetName) { - FmtOptions = new Dictionary(); this.FacetName = facetName; } @@ -39,19 +36,12 @@ public Hashtable GetRequestParameters() parameters.Add(Constants.FACET_NAME, this.FacetName); } - if (this.ShowHiddenFacets) + if (this.FmtOptions != null) { - this.FmtOptions.Add(Constants.SHOW_HIDDEN_FACETS, this.ShowHiddenFacets.ToString()); - } - - if (this.ShowProtectedFacets) - { - this.FmtOptions.Add(Constants.SHOW_PROTECTED_FACETS, this.ShowProtectedFacets.ToString()); - } - - if (this.FmtOptions != null && this.FmtOptions.Count != 0) - { - parameters.Add(Constants.FMT_OPTIONS, this.FmtOptions); + foreach (DictionaryEntry entry in this.FmtOptions.GetQueryParameters()) + { + parameters.Add(entry.Key, entry.Value); + } } return parameters; diff --git a/src/constructor.io/models/Browse/BrowseFacetsRequest.cs b/src/constructor.io/models/Browse/BrowseFacetsRequest.cs index 58b5056c..443922d1 100644 --- a/src/constructor.io/models/Browse/BrowseFacetsRequest.cs +++ b/src/constructor.io/models/Browse/BrowseFacetsRequest.cs @@ -13,18 +13,8 @@ public class BrowseFacetsRequest public int Page { get; set; } public int ResultsPerPage { get; set; } public int Offset { get; set; } - public bool ShowHiddenFacets { get; set; } - public bool ShowProtectedFacets { get; set; } + public FmtOptions FmtOptions { get; set; } public UserInfo UserInfo { get; set; } - private Dictionary FmtOptions { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public BrowseFacetsRequest() - { - FmtOptions = new Dictionary(); - } /// /// Get request parameters. @@ -49,19 +39,12 @@ public Hashtable GetRequestParameters() parameters.Add(Constants.RESULTS_PER_PAGE, this.ResultsPerPage); } - if (this.ShowHiddenFacets) + if (this.FmtOptions != null) { - this.FmtOptions.Add(Constants.SHOW_HIDDEN_FACETS, this.ShowHiddenFacets.ToString()); - } - - if (this.ShowProtectedFacets) - { - this.FmtOptions.Add(Constants.SHOW_PROTECTED_FACETS, this.ShowProtectedFacets.ToString()); - } - - if (this.FmtOptions != null && this.FmtOptions.Count != 0) - { - parameters.Add(Constants.FMT_OPTIONS, this.FmtOptions); + foreach (DictionaryEntry entry in this.FmtOptions.GetQueryParameters()) + { + parameters.Add(entry.Key, entry.Value); + } } return parameters; diff --git a/src/constructor.io/models/Browse/BrowseItemsRequest.cs b/src/constructor.io/models/Browse/BrowseItemsRequest.cs index 60179f6b..41d1b249 100644 --- a/src/constructor.io/models/Browse/BrowseItemsRequest.cs +++ b/src/constructor.io/models/Browse/BrowseItemsRequest.cs @@ -13,9 +13,7 @@ public class BrowseItemsRequest { public List ItemIds { get; set; } public Dictionary> Filters { get; set; } - public Dictionary FmtOptions { get; set; } - public List HiddenFields { get; set; } - public List HiddenFacets { get; set; } + public FmtOptions FmtOptions { get; set; } public int Offset { get; set; } public int Page { get; set; } public int ResultsPerPage { get; set; } @@ -83,17 +81,10 @@ public Hashtable GetRequestParameters() if (this.FmtOptions != null) { - parameters.Add(Constants.FMT_OPTIONS, this.FmtOptions); - } - - if (this.HiddenFields != null) - { - parameters.Add(Constants.HIDDEN_FIELDS, this.HiddenFields); - } - - if (this.HiddenFacets != null) - { - parameters.Add(Constants.HIDDEN_FACETS, this.HiddenFacets); + foreach (DictionaryEntry entry in this.FmtOptions.GetQueryParameters()) + { + parameters.Add(entry.Key, entry.Value); + } } if (this.Offset != 0) diff --git a/src/constructor.io/models/Browse/BrowseRequest.cs b/src/constructor.io/models/Browse/BrowseRequest.cs index 19b32d14..5e3037dd 100644 --- a/src/constructor.io/models/Browse/BrowseRequest.cs +++ b/src/constructor.io/models/Browse/BrowseRequest.cs @@ -25,23 +25,13 @@ public class BrowseRequest : IPlpRequest /// /// Gets or sets the format options used to refine result groups. /// - public Dictionary FmtOptions { get; set; } + public FmtOptions FmtOptions { get; set; } /// /// Gets or sets the filtering expression used to scope search results. /// public PreFilterExpression PreFilterExpression { get; set; } - /// - /// Gets or sets hidden metadata fields to return. - /// - public List HiddenFields { get; set; } - - /// - /// Gets or sets hidden facets fields to return. - /// - public List HiddenFacets { get; set; } - /// /// Gets or sets the number of results to skip from the beginning. /// Can't be used together with . @@ -145,25 +135,18 @@ public Hashtable GetRequestParameters() parameters.Add(Constants.FILTERS, this.Filters); } - if (this.FmtOptions != null) - { - parameters.Add(Constants.FMT_OPTIONS, this.FmtOptions); - } - if (this.PreFilterExpression != null) { string preFilterJson = this.PreFilterExpression.GetExpression(); parameters.Add(Constants.PRE_FILTER_EXPRESSION, preFilterJson); } - if (this.HiddenFields != null) - { - parameters.Add(Constants.HIDDEN_FIELDS, this.HiddenFields); - } - - if (this.HiddenFacets != null) + if (this.FmtOptions != null) { - parameters.Add(Constants.HIDDEN_FACETS, this.HiddenFacets); + foreach (DictionaryEntry entry in this.FmtOptions.GetQueryParameters()) + { + parameters.Add(entry.Key, entry.Value); + } } if (this.Offset != 0) diff --git a/src/constructor.io/models/Recommendations/RecommendationsRequest.cs b/src/constructor.io/models/Recommendations/RecommendationsRequest.cs index 71eef298..04a9eace 100644 --- a/src/constructor.io/models/Recommendations/RecommendationsRequest.cs +++ b/src/constructor.io/models/Recommendations/RecommendationsRequest.cs @@ -80,6 +80,11 @@ public RecommendationsRequest(string podId) /// public PreFilterExpression PreFilterExpression { get; set; } + /// + /// Gets or sets format options to control result formatting. + /// + public FmtOptions FmtOptions { get; set; } + /// /// Get request parameters. /// @@ -158,6 +163,14 @@ public Hashtable GetRequestParameters() parameters.Add(Constants.PRE_FILTER_EXPRESSION, preFilterJson); } + if (this.FmtOptions != null) + { + foreach (DictionaryEntry entry in this.FmtOptions.GetQueryParameters()) + { + parameters.Add(entry.Key, entry.Value); + } + } + return parameters; } diff --git a/src/constructor.io/models/Search/SearchRequest.cs b/src/constructor.io/models/Search/SearchRequest.cs index a2c98f9e..baa3bb1d 100644 --- a/src/constructor.io/models/Search/SearchRequest.cs +++ b/src/constructor.io/models/Search/SearchRequest.cs @@ -25,23 +25,13 @@ public class SearchRequest : IPlpRequest /// /// Gets or sets the format options used to refine result groups. /// - public Dictionary FmtOptions { get; set; } + public FmtOptions FmtOptions { get; set; } /// /// Gets or sets the filtering expression used to scope search results. /// public PreFilterExpression PreFilterExpression { get; set; } - /// - /// Gets or sets hidden metadata fields to return. - /// - public List HiddenFields { get; set; } - - /// - /// Gets or sets hidden facets fields to return. - /// - public List HiddenFacets { get; set; } - /// /// Gets or sets the number of results to skip from the beginning. /// Can't be used together with . @@ -142,17 +132,10 @@ public Hashtable GetRequestParameters() if (this.FmtOptions != null) { - parameters.Add(Constants.FMT_OPTIONS, this.FmtOptions); - } - - if (this.HiddenFields != null) - { - parameters.Add(Constants.HIDDEN_FIELDS, this.HiddenFields); - } - - if (this.HiddenFacets != null) - { - parameters.Add(Constants.HIDDEN_FACETS, this.HiddenFacets); + foreach (DictionaryEntry entry in this.FmtOptions.GetQueryParameters()) + { + parameters.Add(entry.Key, entry.Value); + } } if (this.Offset != 0) diff --git a/src/constructor.io/models/common/FmtOptions.cs b/src/constructor.io/models/common/FmtOptions.cs new file mode 100644 index 00000000..0ce5a6c6 --- /dev/null +++ b/src/constructor.io/models/common/FmtOptions.cs @@ -0,0 +1,116 @@ +using System.Collections; +using System.Collections.Generic; +using Constructorio_NET.Utils; + +namespace Constructorio_NET.Models +{ + /// + /// Format options used to refine result groups and control response fields. + /// + public class FmtOptions + { + /// + /// Gets or sets the maximum depth of result groups to return. + /// + public int? GroupsMaxDepth { get; set; } + + /// + /// Gets or sets the starting point for groups. + /// Valid values: "current", "top", or "group_id:{id}". + /// + public string? GroupsStart { get; set; } + + /// + /// Gets or sets the list of fields to return in results. + /// + public List? Fields { get; set; } + + /// + /// Gets or sets hidden metadata fields to return. + /// + public List? HiddenFields { get; set; } + + /// + /// Gets or sets hidden facet fields to return. + /// + public List? HiddenFacets { get; set; } + + /// + /// Gets or sets whether to show hidden fields. + /// + public bool? ShowHiddenFields { get; set; } + + /// + /// Gets or sets the variations return type. + /// Valid values: "default", "all", "matched". + /// + public string? VariationsReturnType { get; set; } + + /// + /// Gets or sets whether to show hidden facets. + /// + public bool? ShowHiddenFacets { get; set; } + + /// + /// Gets or sets whether to show protected facets. + /// + public bool? ShowProtectedFacets { get; set; } + + /// + /// Returns a Hashtable of pre-formatted query parameters with keys like "fmt_options[property_name]". + /// Values are either string or List<string>. + /// + /// Hashtable of query parameters. + public Hashtable GetQueryParameters() + { + Hashtable parameters = new Hashtable(); + + if (this.GroupsMaxDepth.HasValue) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.GROUPS_MAX_DEPTH}]", this.GroupsMaxDepth.Value.ToString()); + } + + if (!string.IsNullOrEmpty(this.GroupsStart)) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.GROUPS_START}]", this.GroupsStart); + } + + if (this.ShowHiddenFields.HasValue) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FIELDS}]", this.ShowHiddenFields.Value.ToString().ToLower()); + } + + if (!string.IsNullOrEmpty(this.VariationsReturnType)) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.VARIATIONS_RETURN_TYPE}]", this.VariationsReturnType); + } + + if (this.ShowHiddenFacets.HasValue) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.SHOW_HIDDEN_FACETS}]", this.ShowHiddenFacets.Value.ToString().ToLower()); + } + + if (this.ShowProtectedFacets.HasValue) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.SHOW_PROTECTED_FACETS}]", this.ShowProtectedFacets.Value.ToString().ToLower()); + } + + if (this.Fields != null) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.FIELDS}]", this.Fields); + } + + if (this.HiddenFields != null) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FIELDS}]", this.HiddenFields); + } + + if (this.HiddenFacets != null) + { + parameters.Add($"{Constants.FMT_OPTIONS}[{Constants.HIDDEN_FACETS}]", this.HiddenFacets); + } + + return parameters; + } + } +} diff --git a/src/constructor.io/models/common/IPlpRequest.cs b/src/constructor.io/models/common/IPlpRequest.cs index c9bb8eb1..e895de41 100644 --- a/src/constructor.io/models/common/IPlpRequest.cs +++ b/src/constructor.io/models/common/IPlpRequest.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace Constructorio_NET.Models { public interface IPlpRequest : IFilterable, IPageable, ISortable, IUserDetails @@ -7,17 +5,7 @@ public interface IPlpRequest : IFilterable, IPageable, ISortable, IUserDetails /// /// Gets or sets the format options used to refine result groups. /// - Dictionary FmtOptions { get; set; } - - /// - /// Gets or sets hidden facets fields to return. - /// - List HiddenFacets { get; set; } - - /// - /// Gets or sets hidden metadata fields to return. - /// - List HiddenFields { get; set; } + FmtOptions FmtOptions { get; set; } /// /// Gets or sets the filtering expression used to scope search results. diff --git a/src/constructor.io/utils/Constants.cs b/src/constructor.io/utils/Constants.cs index 69ed876e..cc6e43a9 100644 --- a/src/constructor.io/utils/Constants.cs +++ b/src/constructor.io/utils/Constants.cs @@ -9,8 +9,11 @@ public static class Constants public const string FACET_NAME = "facet_name"; public const string FILTERS = "filters"; public const string FILTERS_PER_SECTION = "filters_per_section"; + public const string FIELDS = "fields"; public const string FMT_OPTIONS = "fmt_options"; public const string FORCE = "force"; + public const string GROUPS_MAX_DEPTH = "groups_max_depth"; + public const string GROUPS_START = "groups_start"; public const string HIDDEN_FIELDS = "hidden_fields"; public const string HIDDEN_FACETS = "hidden_facets"; public const string ITEM_IDS = "ids"; @@ -19,6 +22,7 @@ public static class Constants public const string RESULTS_PER_PAGE = "num_results_per_page"; public const string SECURITY_TOKEN = "x-cnstrc-token"; public const string SHOW_HIDDEN_FACETS = "show_hidden_facets"; + public const string SHOW_HIDDEN_FIELDS = "show_hidden_fields"; public const string SHOW_PROTECTED_FACETS = "show_protected_facets"; public const string USER_SEGMENTS = "us"; public const string SECTION = "section"; @@ -33,6 +37,7 @@ public static class Constants public const string USER_ID = "ui"; public const string USER_IP = "X-Forwarded-For"; public const string VARIATIONS_MAP = "variations_map"; + public const string VARIATIONS_RETURN_TYPE = "variations_return_type"; public const string START_DATE = "start_date"; public const string END_DATE = "end_date"; public const string STATUS = "status"; diff --git a/src/constructor.io/utils/Helpers.cs b/src/constructor.io/utils/Helpers.cs index 5b15bc4b..56f85bb8 100644 --- a/src/constructor.io/utils/Helpers.cs +++ b/src/constructor.io/utils/Helpers.cs @@ -177,47 +177,6 @@ protected static string MakeUrl(Hashtable options, List paths, Hashtable } } - // Add format options to query string - if (queryParams.Contains(Constants.FMT_OPTIONS)) - { - Dictionary fmtOptions = (Dictionary)queryParams[Constants.FMT_OPTIONS]; - queryParams.Remove(Constants.FMT_OPTIONS); - - foreach (var fmtOption in fmtOptions) - { - url.Append("&" + Constants.FMT_OPTIONS + UrlEscapedStartSquareBracket) - .Append(OurEscapeDataString(fmtOption.Key)) - .Append(UrlEscapedEndSquareBracket + "=") - .Append(OurEscapeDataString(fmtOption.Value)); - } - } - - // Add hidden fields as fmt_options - if (queryParams.Contains(Constants.HIDDEN_FIELDS)) - { - List hiddenFields = (List)queryParams[Constants.HIDDEN_FIELDS]; - queryParams.Remove(Constants.HIDDEN_FIELDS); - - foreach (var hiddenField in hiddenFields) - { - url.Append("&" + Constants.FMT_OPTIONS + UrlEscapedStartSquareBracket + Constants.HIDDEN_FIELDS + UrlEscapedEndSquareBracket + "=") - .Append(OurEscapeDataString(hiddenField)); - } - } - - // Add hidden facets as fmt_options - if (queryParams.Contains(Constants.HIDDEN_FACETS)) - { - List hiddenFacets = (List)queryParams[Constants.HIDDEN_FACETS]; - queryParams.Remove(Constants.HIDDEN_FACETS); - - foreach (var hiddenFacet in hiddenFacets) - { - url.Append("&" + Constants.FMT_OPTIONS + UrlEscapedStartSquareBracket + Constants.HIDDEN_FACETS + UrlEscapedEndSquareBracket + "=") - .Append(OurEscapeDataString(hiddenFacet)); - } - } - // Add quiz answers to query string if (queryParams.Contains(Constants.ANSWERS)) {