From 04816a0242218f0114bfdbed62829342a1ae52e1 Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Mon, 16 Mar 2020 10:20:45 +0200 Subject: [PATCH 01/11] Look for presets in base theme if current preset specified in current theme --- .../ShopifyLiquidThemeEngine.cs | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index cc2bfb116..5965bbf51 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -358,13 +358,26 @@ public IDictionary GetSettings(string defaultValue = null) JObject result; var baseThemeSettings = new JObject(); - var currentThemeSettings = result = GetCurrentSettingsPreset(InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath)); + var allCurrentThemeSettings = InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath); + var currentThemeSettings = result = null; + try + { + currentThemeSettings = result = GetCurrentSettingsPreset(allCurrentThemeSettings); + } + catch (StorefrontException) when (_options.MergeBaseSettings) + { + // Do not throw exception of missed presets or current preset if we merge settings + } //Try to load settings from base theme path and merge them with resources for local theme if ((_options.MergeBaseSettings || currentThemeSettings == null) && !string.IsNullOrEmpty(BaseThemeSettingPath)) { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(BaseThemeSettingPath) })); - result = baseThemeSettings = GetCurrentSettingsPreset(InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath)); + var allBaseThemeSettings = InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath); + result = baseThemeSettings = GetCurrentSettingsPreset(allBaseThemeSettings, + _options.MergeBaseSettings && currentThemeSettings == null + ? allCurrentThemeSettings + : null); } if (_options.MergeBaseSettings) @@ -480,23 +493,27 @@ private static JObject InnerGetAllSettings(IContentBlobProvider themeBlobProvide /// Get actual preset from config /// /// - private static JObject GetCurrentSettingsPreset(JObject allSettings) + private static JObject GetCurrentSettingsPreset(JObject allSettings, JObject baseSettings = null) { var result = allSettings; - var currentPreset = allSettings.GetValue("current"); + var currentPreset = (baseSettings ?? allSettings).GetValue("current"); if (currentPreset is JValue currentPresetValue) { var currentPresetName = currentPresetValue.Value.ToString(); - if (!(allSettings.GetValue("presets") is JObject presets) || !presets.Children().Any()) + if (!string.IsNullOrEmpty(currentPresetName)) { - throw new StorefrontException("Setting presets not defined"); - } + if (!(allSettings.GetValue("presets") is JObject presets) || + !presets.Children().Any()) + { + throw new StorefrontException("Setting presets not defined"); + } - IList allPresets = presets.Children().Cast().ToList(); - result = allPresets.FirstOrDefault(p => p.Name == currentPresetName)?.Value as JObject; - if (result == null) - { - throw new StorefrontException($"Setting preset with name '{currentPresetName}' not found"); + IList allPresets = presets.Children().Cast().ToList(); + result = allPresets.FirstOrDefault(p => p.Name == currentPresetName)?.Value as JObject; + if (result == null) + { + throw new StorefrontException($"Setting preset with name '{currentPresetName}' not found"); + } } } if (currentPreset is JObject preset) From 3bdfc8c80ee149218d6e888d33c89da6ce28d729 Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Mon, 16 Mar 2020 18:44:11 +0200 Subject: [PATCH 02/11] Fixed bug with additional settings in current theme if preset specified --- VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index 5965bbf51..14d309ce7 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -367,6 +367,8 @@ public IDictionary GetSettings(string defaultValue = null) catch (StorefrontException) when (_options.MergeBaseSettings) { // Do not throw exception of missed presets or current preset if we merge settings + // Instead treat current settings as json object ("flat" settings) and merge them + currentThemeSettings = allCurrentThemeSettings; } //Try to load settings from base theme path and merge them with resources for local theme From 4dc09ab32061edb7e4319e844ef21e3d165f8e21 Mon Sep 17 00:00:00 2001 From: Eugeny Tatarincev Date: Tue, 17 Mar 2020 17:56:11 +0200 Subject: [PATCH 03/11] Add SettingJsonOverlayMerger --- .../SettingsJsonOverlayMerger.cs | 90 +++++++++++++++++++ .../ShopifyLiquidThemeEngine.cs | 58 ++---------- 2 files changed, 95 insertions(+), 53 deletions(-) create mode 100644 VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs diff --git a/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs b/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs new file mode 100644 index 000000000..4bb9b6700 --- /dev/null +++ b/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; +using VirtoCommerce.Storefront.Model.Common.Exceptions; + +namespace VirtoCommerce.LiquidThemeEngine +{ + public static class SettingJsonOverlayMerger + { + internal class JsonPresetsDoc + { + public JsonPresset Current { get; set; } + public IList Pressets { get; set; } = new List(); + } + + internal class JsonPresset + { + public bool NameIsSet => !string.IsNullOrEmpty(Name); + public string Name { get; set; } + public JObject Json { get; set; } + } + + public static JObject Merge(JObject baseJson, JObject headJson) + { + if (baseJson == null) + { + throw new ArgumentNullException(nameof(baseJson)); + } + if (headJson == null) + { + throw new ArgumentNullException(nameof(headJson)); + } + + var basePresetsDoc = ReadPresets(baseJson); + var headPresetsDoc = ReadPresets(headJson); + //Change base current preset based on head value + if (headPresetsDoc.Current.NameIsSet) + { + basePresetsDoc.Current = basePresetsDoc.Pressets.FirstOrDefault(x => x.Name == headPresetsDoc.Current.Name); + } + var result = basePresetsDoc.Current.Json; + result.Merge(headPresetsDoc.Current.Json, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); + return result; + } + + private static JsonPresetsDoc ReadPresets(JObject json) + { + var result = new JsonPresetsDoc + { + Current = new JsonPresset + { + Json = json + } + }; + + if (json.GetValue("presets") is JObject presets) + { + var allJsonPresets = presets.Children().Cast().ToList(); + foreach (var jsonPreset in allJsonPresets) + { + var presset = new JsonPresset + { + Name = jsonPreset.Name, + Json = jsonPreset.Value as JObject + }; + result.Pressets.Add(presset); + } + } + + var currentPreset = json.GetValue("current"); + if (currentPreset is JValue currentPresetValue) + { + var presetName = currentPresetValue.Value.ToString(); + var currentJson = result.Pressets.FirstOrDefault(x => x.Name == presetName)?.Json; + if (currentJson == null && result.Pressets.Any()) + { + throw new StorefrontException($"Setting preset with name '{presetName}' not found"); + } + result.Current = new JsonPresset { Name = presetName, Json = currentJson ?? json }; + } + if (currentPreset is JObject preset) + { + result.Current.Json = preset; + } + + return result; + } + } +} diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index 14d309ce7..250cb1f52 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -358,34 +358,19 @@ public IDictionary GetSettings(string defaultValue = null) JObject result; var baseThemeSettings = new JObject(); - var allCurrentThemeSettings = InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath); - var currentThemeSettings = result = null; - try - { - currentThemeSettings = result = GetCurrentSettingsPreset(allCurrentThemeSettings); - } - catch (StorefrontException) when (_options.MergeBaseSettings) - { - // Do not throw exception of missed presets or current preset if we merge settings - // Instead treat current settings as json object ("flat" settings) and merge them - currentThemeSettings = allCurrentThemeSettings; - } + var currentThemeSettings = result = InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath); //Try to load settings from base theme path and merge them with resources for local theme if ((_options.MergeBaseSettings || currentThemeSettings == null) && !string.IsNullOrEmpty(BaseThemeSettingPath)) { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(BaseThemeSettingPath) })); - var allBaseThemeSettings = InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath); - result = baseThemeSettings = GetCurrentSettingsPreset(allBaseThemeSettings, - _options.MergeBaseSettings && currentThemeSettings == null - ? allCurrentThemeSettings - : null); + result = baseThemeSettings = InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath); } if (_options.MergeBaseSettings) { result = baseThemeSettings; - result.Merge(currentThemeSettings ?? new JObject(), new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); + result = SettingJsonOverlayMerger.Merge(result, currentThemeSettings ?? new JObject()); } return result.ToObject>().ToDictionary(x => x.Key, x => x.Value).WithDefaultValue(defaultValue); @@ -408,7 +393,7 @@ public JObject ReadLocalization() if (BaseThemeLocalePath != null) { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(BaseThemeLocalePath + "/*") })); - result = InnerReadLocalization(_themeBlobProvider, BaseThemeLocalePath, WorkContext.CurrentLanguage); + result = InnerReadLocalization(_themeBlobProvider, BaseThemeLocalePath, WorkContext.CurrentLanguage) ?? new JObject(); } result.Merge(InnerReadLocalization(_themeBlobProvider, CurrentThemeLocalePath, WorkContext.CurrentLanguage) ?? new JObject(), new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); return result; @@ -491,40 +476,7 @@ private static JObject InnerGetAllSettings(IContentBlobProvider themeBlobProvide return result; } - /// - /// Get actual preset from config - /// - /// - private static JObject GetCurrentSettingsPreset(JObject allSettings, JObject baseSettings = null) - { - var result = allSettings; - var currentPreset = (baseSettings ?? allSettings).GetValue("current"); - if (currentPreset is JValue currentPresetValue) - { - var currentPresetName = currentPresetValue.Value.ToString(); - if (!string.IsNullOrEmpty(currentPresetName)) - { - if (!(allSettings.GetValue("presets") is JObject presets) || - !presets.Children().Any()) - { - throw new StorefrontException("Setting presets not defined"); - } - - IList allPresets = presets.Children().Cast().ToList(); - result = allPresets.FirstOrDefault(p => p.Name == currentPresetName)?.Value as JObject; - if (result == null) - { - throw new StorefrontException($"Setting preset with name '{currentPresetName}' not found"); - } - } - } - if (currentPreset is JObject preset) - { - result = preset; - } - - return result; - } + private string ReadTemplateByPath(string templatePath) { From b45eb923ae561dc1fc6ba34d5fbb1bf7cfde75d6 Mon Sep 17 00:00:00 2001 From: Eugeny Tatarincev Date: Tue, 17 Mar 2020 18:08:13 +0200 Subject: [PATCH 04/11] Fix typo --- .../SettingsJsonOverlayMerger.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs b/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs index 4bb9b6700..8a59261f1 100644 --- a/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs +++ b/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs @@ -10,11 +10,11 @@ public static class SettingJsonOverlayMerger { internal class JsonPresetsDoc { - public JsonPresset Current { get; set; } - public IList Pressets { get; set; } = new List(); + public JsonPreset Current { get; set; } + public IList Presets { get; set; } = new List(); } - internal class JsonPresset + internal class JsonPreset { public bool NameIsSet => !string.IsNullOrEmpty(Name); public string Name { get; set; } @@ -34,10 +34,10 @@ public static JObject Merge(JObject baseJson, JObject headJson) var basePresetsDoc = ReadPresets(baseJson); var headPresetsDoc = ReadPresets(headJson); - //Change base current preset based on head value + //Change the current preset for base doc according to head preset value if it specified if (headPresetsDoc.Current.NameIsSet) { - basePresetsDoc.Current = basePresetsDoc.Pressets.FirstOrDefault(x => x.Name == headPresetsDoc.Current.Name); + basePresetsDoc.Current = basePresetsDoc.Presets.FirstOrDefault(x => x.Name == headPresetsDoc.Current.Name); } var result = basePresetsDoc.Current.Json; result.Merge(headPresetsDoc.Current.Json, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); @@ -48,7 +48,7 @@ private static JsonPresetsDoc ReadPresets(JObject json) { var result = new JsonPresetsDoc { - Current = new JsonPresset + Current = new JsonPreset { Json = json } @@ -59,12 +59,12 @@ private static JsonPresetsDoc ReadPresets(JObject json) var allJsonPresets = presets.Children().Cast().ToList(); foreach (var jsonPreset in allJsonPresets) { - var presset = new JsonPresset + var presset = new JsonPreset { Name = jsonPreset.Name, Json = jsonPreset.Value as JObject }; - result.Pressets.Add(presset); + result.Presets.Add(presset); } } @@ -72,12 +72,12 @@ private static JsonPresetsDoc ReadPresets(JObject json) if (currentPreset is JValue currentPresetValue) { var presetName = currentPresetValue.Value.ToString(); - var currentJson = result.Pressets.FirstOrDefault(x => x.Name == presetName)?.Json; - if (currentJson == null && result.Pressets.Any()) + var currentJson = result.Presets.FirstOrDefault(x => x.Name == presetName)?.Json; + if (currentJson == null && result.Presets.Any()) { throw new StorefrontException($"Setting preset with name '{presetName}' not found"); } - result.Current = new JsonPresset { Name = presetName, Json = currentJson ?? json }; + result.Current = new JsonPreset { Name = presetName, Json = currentJson ?? json }; } if (currentPreset is JObject preset) { From f11731da9decbabccc6c88d5dc7cafd918ff6fef Mon Sep 17 00:00:00 2001 From: Eugeny Tatarincev Date: Tue, 17 Mar 2020 18:10:09 +0200 Subject: [PATCH 05/11] Fix naming --- .../SettingsJsonOverlayMerger.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs b/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs index 8a59261f1..566207f70 100644 --- a/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs +++ b/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs @@ -8,9 +8,9 @@ namespace VirtoCommerce.LiquidThemeEngine { public static class SettingJsonOverlayMerger { - internal class JsonPresetsDoc + internal class JsonSettingDoc { - public JsonPreset Current { get; set; } + public JsonPreset CurrentPreset { get; set; } public IList Presets { get; set; } = new List(); } @@ -32,23 +32,23 @@ public static JObject Merge(JObject baseJson, JObject headJson) throw new ArgumentNullException(nameof(headJson)); } - var basePresetsDoc = ReadPresets(baseJson); - var headPresetsDoc = ReadPresets(headJson); + var baseSettingDoc = ReadSettingDoc(baseJson); + var headSettingDoc = ReadSettingDoc(headJson); //Change the current preset for base doc according to head preset value if it specified - if (headPresetsDoc.Current.NameIsSet) + if (headSettingDoc.CurrentPreset.NameIsSet) { - basePresetsDoc.Current = basePresetsDoc.Presets.FirstOrDefault(x => x.Name == headPresetsDoc.Current.Name); + baseSettingDoc.CurrentPreset = baseSettingDoc.Presets.FirstOrDefault(x => x.Name == headSettingDoc.CurrentPreset.Name); } - var result = basePresetsDoc.Current.Json; - result.Merge(headPresetsDoc.Current.Json, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); + var result = baseSettingDoc.CurrentPreset.Json; + result.Merge(headSettingDoc.CurrentPreset.Json, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); return result; } - private static JsonPresetsDoc ReadPresets(JObject json) + private static JsonSettingDoc ReadSettingDoc(JObject json) { - var result = new JsonPresetsDoc + var result = new JsonSettingDoc { - Current = new JsonPreset + CurrentPreset = new JsonPreset { Json = json } @@ -77,11 +77,11 @@ private static JsonPresetsDoc ReadPresets(JObject json) { throw new StorefrontException($"Setting preset with name '{presetName}' not found"); } - result.Current = new JsonPreset { Name = presetName, Json = currentJson ?? json }; + result.CurrentPreset = new JsonPreset { Name = presetName, Json = currentJson ?? json }; } if (currentPreset is JObject preset) { - result.Current.Json = preset; + result.CurrentPreset.Json = preset; } return result; From 4880f3014373fe0ce96808018c7b39a5462d5ad1 Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Wed, 18 Mar 2020 07:03:59 +0200 Subject: [PATCH 06/11] Added tests --- .../ShopifyLiquidThemeEngine.cs | 4 +- .../ShopifyLiquidThemeEngineTests.cs | 258 ++++++++++++++++++ 2 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index 14d309ce7..2c9937dc3 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -359,7 +359,7 @@ public IDictionary GetSettings(string defaultValue = null) JObject result; var baseThemeSettings = new JObject(); var allCurrentThemeSettings = InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath); - var currentThemeSettings = result = null; + JObject currentThemeSettings; try { currentThemeSettings = result = GetCurrentSettingsPreset(allCurrentThemeSettings); @@ -368,7 +368,7 @@ public IDictionary GetSettings(string defaultValue = null) { // Do not throw exception of missed presets or current preset if we merge settings // Instead treat current settings as json object ("flat" settings) and merge them - currentThemeSettings = allCurrentThemeSettings; + currentThemeSettings = result = allCurrentThemeSettings; } //Try to load settings from base theme path and merge them with resources for local theme diff --git a/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs b/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs new file mode 100644 index 000000000..e39e27a98 --- /dev/null +++ b/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs @@ -0,0 +1,258 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; +using Moq; +using Newtonsoft.Json.Linq; +using VirtoCommerce.LiquidThemeEngine; +using VirtoCommerce.Storefront.Model; +using VirtoCommerce.Storefront.Model.Caching; +using VirtoCommerce.Storefront.Model.StaticContent; +using VirtoCommerce.Storefront.Model.Stores; +using Xunit; + +namespace VirtoCommerce.Storefront.Tests.LiquidThemeEngine +{ + public class ShopifyLiquidThemeEngineTests: IDisposable + { + private static readonly string ThemesPath = "Themes"; + private static readonly string BaseThemePath = "odt\\default"; + private static readonly string CurrentThemePath = "odt\\current"; + private static readonly string SettingsPath = "config\\settings_data.json"; + + private static JObject DefaultSettingsWithoutPresets => JObject.Parse(@" + { + 'background_color': '#fff', + 'foreground_color': '#000' + } + "); + + private static JObject DefaultSettingsWithPresets => JObject.Parse(@" + { + 'current': 'Light', + 'presets': { + 'Dark': { + 'background_color': '#000', + 'foreground_color': '#fff' + }, + 'Light': { + 'background_color': '#fff', + 'foreground_color': '#000' + } + } + } + "); + + private static JObject CurrentSettingsWithoutSelectedPreset => JObject.Parse(@" + { + 'foreground_color': '#333' + } + "); + + private static JObject CurrentSettingsWithSelectedPreset => JObject.Parse(@" + { + 'current': 'Light', + 'foreground_color': '#333' + } + "); + + private readonly StreamWriter _defaultThemeStreamWriter = new StreamWriter(new MemoryStream()) { AutoFlush = true }; + private readonly StreamWriter _currentThemeStreamWriter = new StreamWriter(new MemoryStream()) { AutoFlush = true }; + + private Stream DefaultThemeStream { get; set; } + private Stream CurrentThemeStream { get; set; } + + [Fact] + public void Settings_Without_Inheritance_Flat() + { + InitializeStreams(false, false); + Check_Without_Inheritance(); + } + + [Fact] + public void Settings_Without_Inheritance_Presets() + { + InitializeStreams(true, false); + Check_Without_Inheritance(); + } + + private void Check_Without_Inheritance() + { + var options = new LiquidThemeEngineOptions(); + var shopifyLiquidThemeEngine = GetThemeEngine(false, options); + var settings = shopifyLiquidThemeEngine.GetSettings(); + Assert.Equal("#fff", settings["background_color"]); + Assert.Equal("#000", settings["foreground_color"]); + } + + [Fact] + public void Settings_Inheritance_Backward_Compatibility_Base_Theme_Name() + { + var options = new LiquidThemeEngineOptions() + { +#pragma warning disable 618 + BaseThemeName = "odt" +#pragma warning restore 618 + }; + + Check_Inheritance_Backward_Compatibility(options); + } + + [Fact] + public void Settings_Inheritance_Backward_Compatibility_Base_Theme_Path_Without_Merge() + { + var options = new LiquidThemeEngineOptions() + { + BaseThemePath = "odt\\default" + }; + + Check_Inheritance_Backward_Compatibility(options); + } + + private void Check_Inheritance_Backward_Compatibility(LiquidThemeEngineOptions options) + { + var shopifyLiquidThemeEngine = GetThemeEngine(true, options); + InitializeStreams(false, false); + var settings = shopifyLiquidThemeEngine.GetSettings(); + Assert.False(settings.ContainsKey("background_color")); + Assert.Equal("#333", settings["foreground_color"]); + } + + [Fact] + public void Settings_Inheritance_Both_Are_Flat() + { + InitializeStreams(false, false); + Check_Colors_In_Merged_Settings(); + } + + [Fact] + public void Settings_Inheritance_Base_Has_Preset_Current_Is_Flat() + { + InitializeStreams(true, false); + Check_Colors_In_Merged_Settings(); + } + + [Fact] + public void Settings_Inheritance_Current_Select_Preset_From_Base() + { + InitializeStreams(true, true); + Check_Colors_In_Merged_Settings(); + } + + private void Check_Colors_In_Merged_Settings() + { + var options = new LiquidThemeEngineOptions() + { + BaseThemePath = "odt\\default", + MergeBaseSettings = true + }; + var shopifyLiquidThemeEngine = GetThemeEngine(true, options); + var settings = shopifyLiquidThemeEngine.GetSettings(); + Assert.Equal("#fff", settings["background_color"]); + Assert.Equal("#333", settings["foreground_color"]); + } + + private void InitializeStreams(bool defaultThemeHasPresets, bool currentThemeHasSelectedPreset) + { + InitializeStream(_defaultThemeStreamWriter, out var defaultThemeStream, defaultThemeHasPresets ? DefaultSettingsWithPresets : DefaultSettingsWithoutPresets); + DefaultThemeStream = defaultThemeStream; + + InitializeStream(_currentThemeStreamWriter, out var currentThemeStream, currentThemeHasSelectedPreset ? CurrentSettingsWithSelectedPreset : CurrentSettingsWithoutSelectedPreset); + CurrentThemeStream = currentThemeStream; + } + + private void InitializeStream(StreamWriter writer, out Stream stream, T content) + { + // Clear + writer.BaseStream.Position = 0; + writer.Flush(); + // Write + writer.Write(content); + // Reset position + writer.BaseStream.Position = 0; + // Copy, because stream reader will automatically destroy it + stream = new MemoryStream(); + writer.BaseStream.CopyTo(stream); + stream.Position = 0; + } + + private IContentBlobProvider ContentBlobProvider + { + get + { + var mock = new Mock(); + var baseThemeSettingsPath = Path.Combine(ThemesPath, BaseThemePath, SettingsPath); + mock.Setup(service => service.PathExists(baseThemeSettingsPath)) + .Returns(() => true); + mock.Setup(service => service.OpenRead(baseThemeSettingsPath)) + .Returns(() => DefaultThemeStream); + var currentThemeSettingsPath = Path.Combine(ThemesPath, CurrentThemePath, SettingsPath); + mock.Setup(service => service.PathExists(currentThemeSettingsPath)) + .Returns(() => true); + mock.Setup(service => service.OpenRead(currentThemeSettingsPath)) + .Returns(() => CurrentThemeStream); + return mock.Object; + } + } + + public IStorefrontMemoryCache MemoryCache + { + get + { + var cacheEntry = Mock.Of(); + Mock.Get(cacheEntry).SetupGet(c => c.ExpirationTokens).Returns(new List()); + var memoryCacheMock = new Mock(); + memoryCacheMock + .Setup(x => x.CreateEntry(It.IsAny())) + .Returns((string key) => cacheEntry); + + memoryCacheMock.Setup(c => c.GetDefaultCacheEntryOptions()).Returns( + new MemoryCacheEntryOptions()); + return memoryCacheMock.Object; + } + } + + private IWorkContextAccessor GetWorkContextAccessor(bool useThemesInheritance) + { + var mock = new Mock(); + mock.Setup(service => service.WorkContext) + .Returns(() => new WorkContext + { + CurrentStore = new Store + { + Id = "odt", + ThemeName = useThemesInheritance ? "current" : "default" + } + }); + return mock.Object; + } + + private IHttpContextAccessor HttpContextAccessor + { + get + { + var mock = new Mock(); + mock.Setup(service => service.HttpContext.Request.Query["preview_mode"]) + .Returns(() => Enumerable.Empty().ToArray()); + return mock.Object; + } + } + + private ShopifyLiquidThemeEngine GetThemeEngine(bool useThemesInheritance, LiquidThemeEngineOptions options) + { + return new ShopifyLiquidThemeEngine(MemoryCache, GetWorkContextAccessor(useThemesInheritance), HttpContextAccessor, + null, ContentBlobProvider, null, new OptionsWrapper(options)); + } + + public void Dispose() + { + MemoryCache.Dispose(); + _defaultThemeStreamWriter.Dispose(); + _currentThemeStreamWriter.Dispose(); + } + } +} From e0a8eed58281c0af9e925596fdf458a4e9f6d513 Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Wed, 18 Mar 2020 09:27:26 +0200 Subject: [PATCH 07/11] Fixed tests & bug in theme --- .../ShopifyLiquidThemeEngine.cs | 12 +++++++----- .../ShopifyLiquidThemeEngineTests.cs | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index 2c9937dc3..a215a1eaf 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -356,10 +356,10 @@ public IDictionary GetSettings(string defaultValue = null) { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(CurrentThemeSettingPath) })); - JObject result; + JObject result = null; var baseThemeSettings = new JObject(); var allCurrentThemeSettings = InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath); - JObject currentThemeSettings; + JObject currentThemeSettings = null; try { currentThemeSettings = result = GetCurrentSettingsPreset(allCurrentThemeSettings); @@ -367,8 +367,6 @@ public IDictionary GetSettings(string defaultValue = null) catch (StorefrontException) when (_options.MergeBaseSettings) { // Do not throw exception of missed presets or current preset if we merge settings - // Instead treat current settings as json object ("flat" settings) and merge them - currentThemeSettings = result = allCurrentThemeSettings; } //Try to load settings from base theme path and merge them with resources for local theme @@ -385,10 +383,14 @@ public IDictionary GetSettings(string defaultValue = null) if (_options.MergeBaseSettings) { result = baseThemeSettings; + if (currentThemeSettings == null) + { + currentThemeSettings = allCurrentThemeSettings; + } result.Merge(currentThemeSettings ?? new JObject(), new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); } - return result.ToObject>().ToDictionary(x => x.Key, x => x.Value).WithDefaultValue(defaultValue); + return result?.ToObject>().ToDictionary(x => x.Key, x => x.Value).WithDefaultValue(defaultValue); }); } diff --git a/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs b/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs index e39e27a98..f26988168 100644 --- a/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs +++ b/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs @@ -55,7 +55,7 @@ public class ShopifyLiquidThemeEngineTests: IDisposable private static JObject CurrentSettingsWithSelectedPreset => JObject.Parse(@" { - 'current': 'Light', + 'current': 'Dark', 'foreground_color': '#333' } "); @@ -140,10 +140,10 @@ public void Settings_Inheritance_Base_Has_Preset_Current_Is_Flat() public void Settings_Inheritance_Current_Select_Preset_From_Base() { InitializeStreams(true, true); - Check_Colors_In_Merged_Settings(); + Check_Colors_In_Merged_Settings(true); } - private void Check_Colors_In_Merged_Settings() + private void Check_Colors_In_Merged_Settings(bool isDarkPreset = false) { var options = new LiquidThemeEngineOptions() { @@ -152,7 +152,7 @@ private void Check_Colors_In_Merged_Settings() }; var shopifyLiquidThemeEngine = GetThemeEngine(true, options); var settings = shopifyLiquidThemeEngine.GetSettings(); - Assert.Equal("#fff", settings["background_color"]); + Assert.Equal(isDarkPreset ? "#000" : "#fff", settings["background_color"]); Assert.Equal("#333", settings["foreground_color"]); } From cdea094af3c8ab2cb8bf959c02627d1115d73a1d Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Wed, 18 Mar 2020 10:07:45 +0200 Subject: [PATCH 08/11] Fixed naming --- .../SettingsJsonOverlayMerger.cs | 90 ------------------ .../SettingsMerger.cs | 92 +++++++++++++++++++ .../ShopifyLiquidThemeEngine.cs | 2 +- 3 files changed, 93 insertions(+), 91 deletions(-) delete mode 100644 VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs create mode 100644 VirtoCommerce.LiquidThemeEngine/SettingsMerger.cs diff --git a/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs b/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs deleted file mode 100644 index 566207f70..000000000 --- a/VirtoCommerce.LiquidThemeEngine/SettingsJsonOverlayMerger.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json.Linq; -using VirtoCommerce.Storefront.Model.Common.Exceptions; - -namespace VirtoCommerce.LiquidThemeEngine -{ - public static class SettingJsonOverlayMerger - { - internal class JsonSettingDoc - { - public JsonPreset CurrentPreset { get; set; } - public IList Presets { get; set; } = new List(); - } - - internal class JsonPreset - { - public bool NameIsSet => !string.IsNullOrEmpty(Name); - public string Name { get; set; } - public JObject Json { get; set; } - } - - public static JObject Merge(JObject baseJson, JObject headJson) - { - if (baseJson == null) - { - throw new ArgumentNullException(nameof(baseJson)); - } - if (headJson == null) - { - throw new ArgumentNullException(nameof(headJson)); - } - - var baseSettingDoc = ReadSettingDoc(baseJson); - var headSettingDoc = ReadSettingDoc(headJson); - //Change the current preset for base doc according to head preset value if it specified - if (headSettingDoc.CurrentPreset.NameIsSet) - { - baseSettingDoc.CurrentPreset = baseSettingDoc.Presets.FirstOrDefault(x => x.Name == headSettingDoc.CurrentPreset.Name); - } - var result = baseSettingDoc.CurrentPreset.Json; - result.Merge(headSettingDoc.CurrentPreset.Json, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); - return result; - } - - private static JsonSettingDoc ReadSettingDoc(JObject json) - { - var result = new JsonSettingDoc - { - CurrentPreset = new JsonPreset - { - Json = json - } - }; - - if (json.GetValue("presets") is JObject presets) - { - var allJsonPresets = presets.Children().Cast().ToList(); - foreach (var jsonPreset in allJsonPresets) - { - var presset = new JsonPreset - { - Name = jsonPreset.Name, - Json = jsonPreset.Value as JObject - }; - result.Presets.Add(presset); - } - } - - var currentPreset = json.GetValue("current"); - if (currentPreset is JValue currentPresetValue) - { - var presetName = currentPresetValue.Value.ToString(); - var currentJson = result.Presets.FirstOrDefault(x => x.Name == presetName)?.Json; - if (currentJson == null && result.Presets.Any()) - { - throw new StorefrontException($"Setting preset with name '{presetName}' not found"); - } - result.CurrentPreset = new JsonPreset { Name = presetName, Json = currentJson ?? json }; - } - if (currentPreset is JObject preset) - { - result.CurrentPreset.Json = preset; - } - - return result; - } - } -} diff --git a/VirtoCommerce.LiquidThemeEngine/SettingsMerger.cs b/VirtoCommerce.LiquidThemeEngine/SettingsMerger.cs new file mode 100644 index 000000000..4c56bbda1 --- /dev/null +++ b/VirtoCommerce.LiquidThemeEngine/SettingsMerger.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; +using VirtoCommerce.Storefront.Model.Common.Exceptions; + +namespace VirtoCommerce.LiquidThemeEngine +{ + public static class SettingsMerger + { + internal class Settings + { + public Preset CurrentPreset { get; set; } + + public IList Presets { get; set; } = new List(); + } + + internal class Preset + { + public string Name { get; set; } + + public JObject Json { get; set; } + } + + public static JObject Merge(JObject baseJson, JObject currentJson) + { + if (baseJson == null) + { + throw new ArgumentNullException(nameof(baseJson)); + } + if (currentJson == null) + { + throw new ArgumentNullException(nameof(currentJson)); + } + + var baseSettings = ReadSettings(baseJson); + var currentSettings = ReadSettings(currentJson); + //Change the current preset for base doc according to head preset value if it specified + if (!string.IsNullOrEmpty(currentSettings.CurrentPreset.Name)) + { + baseSettings.CurrentPreset = baseSettings.Presets.FirstOrDefault(x => x.Name == currentSettings.CurrentPreset.Name); + } + var result = baseSettings.CurrentPreset?.Json ?? new JObject(); + result.Merge(currentSettings.CurrentPreset.Json, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); + return result; + } + + private static Settings ReadSettings(JObject json) + { + var result = new Settings + { + CurrentPreset = new Preset + { + Json = json + } + }; + + if (json.GetValue("presets") is JObject presetsJson) + { + var allPresetsJsonProperties = presetsJson.Children().Cast().ToList(); + foreach (var presetJsonProperty in allPresetsJsonProperties) + { + var preset = new Preset + { + Name = presetJsonProperty.Name, + Json = presetJsonProperty.Value as JObject + }; + result.Presets.Add(preset); + } + } + + var currentPresetJsonToken = json.GetValue("current"); + if (currentPresetJsonToken is JValue currentPresetJsonValue) + { + var presetName = currentPresetJsonValue.Value.ToString(); + var currentPresetJson = result.Presets.FirstOrDefault(x => x.Name == presetName)?.Json; + if (currentPresetJson == null && result.Presets.Any()) + { + throw new StorefrontException($"Setting preset with name '{presetName}' not found"); + } + result.CurrentPreset.Name = presetName; + result.CurrentPreset.Json = currentPresetJson ?? json; + } + if (currentPresetJsonToken is JObject) + { + result.CurrentPreset.Json = currentPresetJsonToken as JObject; + } + + return result; + } + } +} diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index 250cb1f52..0fb967e26 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -370,7 +370,7 @@ public IDictionary GetSettings(string defaultValue = null) if (_options.MergeBaseSettings) { result = baseThemeSettings; - result = SettingJsonOverlayMerger.Merge(result, currentThemeSettings ?? new JObject()); + result = SettingsMerger.Merge(result, currentThemeSettings ?? new JObject()); } return result.ToObject>().ToDictionary(x => x.Key, x => x.Value).WithDefaultValue(defaultValue); From 0dda3036da00bcfcb2e9a69591b5d77afff762ff Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Wed, 18 Mar 2020 10:12:19 +0200 Subject: [PATCH 09/11] Fixed backward compatibility --- .../{SettingsMerger.cs => SettingsManager.cs} | 8 ++++---- .../ShopifyLiquidThemeEngine.cs | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) rename VirtoCommerce.LiquidThemeEngine/{SettingsMerger.cs => SettingsManager.cs} (95%) diff --git a/VirtoCommerce.LiquidThemeEngine/SettingsMerger.cs b/VirtoCommerce.LiquidThemeEngine/SettingsManager.cs similarity index 95% rename from VirtoCommerce.LiquidThemeEngine/SettingsMerger.cs rename to VirtoCommerce.LiquidThemeEngine/SettingsManager.cs index 4c56bbda1..6b8b7d21e 100644 --- a/VirtoCommerce.LiquidThemeEngine/SettingsMerger.cs +++ b/VirtoCommerce.LiquidThemeEngine/SettingsManager.cs @@ -6,16 +6,16 @@ namespace VirtoCommerce.LiquidThemeEngine { - public static class SettingsMerger + public static class SettingsManager { - internal class Settings + public class Settings { public Preset CurrentPreset { get; set; } public IList Presets { get; set; } = new List(); } - internal class Preset + public class Preset { public string Name { get; set; } @@ -45,7 +45,7 @@ public static JObject Merge(JObject baseJson, JObject currentJson) return result; } - private static Settings ReadSettings(JObject json) + public static Settings ReadSettings(JObject json) { var result = new Settings { diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index 0fb967e26..f3afcde3b 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -370,7 +370,11 @@ public IDictionary GetSettings(string defaultValue = null) if (_options.MergeBaseSettings) { result = baseThemeSettings; - result = SettingsMerger.Merge(result, currentThemeSettings ?? new JObject()); + result = SettingsManager.Merge(result, currentThemeSettings ?? new JObject()); + } + else + { + result = SettingsManager.ReadSettings(currentThemeSettings ?? new JObject()).CurrentPreset.Json; } return result.ToObject>().ToDictionary(x => x.Key, x => x.Value).WithDefaultValue(defaultValue); From dc393ced61929bd8887b44a5219e042a48657d5b Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Wed, 18 Mar 2020 10:13:51 +0200 Subject: [PATCH 10/11] Refactoring --- .../ShopifyLiquidThemeEngine.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs index f3afcde3b..7b32522c2 100644 --- a/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs +++ b/VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs @@ -364,18 +364,12 @@ public IDictionary GetSettings(string defaultValue = null) if ((_options.MergeBaseSettings || currentThemeSettings == null) && !string.IsNullOrEmpty(BaseThemeSettingPath)) { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(BaseThemeSettingPath) })); - result = baseThemeSettings = InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath); + baseThemeSettings = InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath); } - if (_options.MergeBaseSettings) - { - result = baseThemeSettings; - result = SettingsManager.Merge(result, currentThemeSettings ?? new JObject()); - } - else - { - result = SettingsManager.ReadSettings(currentThemeSettings ?? new JObject()).CurrentPreset.Json; - } + result = _options.MergeBaseSettings + ? SettingsManager.Merge(baseThemeSettings, currentThemeSettings ?? new JObject()) + : SettingsManager.ReadSettings(currentThemeSettings ?? new JObject()).CurrentPreset.Json; return result.ToObject>().ToDictionary(x => x.Key, x => x.Value).WithDefaultValue(defaultValue); }); From 32fe95ab1e2c893d4070280176a62dea7ad23f53 Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Wed, 18 Mar 2020 10:27:11 +0200 Subject: [PATCH 11/11] Added additional test for case when current is object --- .../ShopifyLiquidThemeEngineTests.cs | 65 ++++++++++++++++--- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs b/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs index f26988168..8bf6240f5 100644 --- a/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs +++ b/VirtoCommerce.Storefront.Tests/LiquidThemeEngine/ShopifyLiquidThemeEngineTests.cs @@ -19,6 +19,13 @@ namespace VirtoCommerce.Storefront.Tests.LiquidThemeEngine { public class ShopifyLiquidThemeEngineTests: IDisposable { + private enum DefaultThemeType + { + WithoutPresets, + WithPresets, + WithPresetsAndCurrentObject + } + private static readonly string ThemesPath = "Themes"; private static readonly string BaseThemePath = "odt\\default"; private static readonly string CurrentThemePath = "odt\\current"; @@ -47,6 +54,25 @@ public class ShopifyLiquidThemeEngineTests: IDisposable } "); + private static JObject DefaultSettingsWithPresetsAndCurrentObject => JObject.Parse(@" + { + 'current': { + 'background_color': '#fff', + 'foreground_color': '#000' + }, + 'presets': { + 'Dark': { + 'background_color': '#000', + 'foreground_color': '#fff' + }, + 'Light': { + 'background_color': '#fff', + 'foreground_color': '#000' + } + } + } + "); + private static JObject CurrentSettingsWithoutSelectedPreset => JObject.Parse(@" { 'foreground_color': '#333' @@ -69,14 +95,21 @@ public class ShopifyLiquidThemeEngineTests: IDisposable [Fact] public void Settings_Without_Inheritance_Flat() { - InitializeStreams(false, false); + InitializeStreams(DefaultThemeType.WithoutPresets, false); Check_Without_Inheritance(); } [Fact] public void Settings_Without_Inheritance_Presets() { - InitializeStreams(true, false); + InitializeStreams(DefaultThemeType.WithPresets, false); + Check_Without_Inheritance(); + } + + [Fact] + public void Settings_Without_Inheritance_Presets_And_Current_Object() + { + InitializeStreams(DefaultThemeType.WithPresetsAndCurrentObject, false); Check_Without_Inheritance(); } @@ -116,7 +149,7 @@ public void Settings_Inheritance_Backward_Compatibility_Base_Theme_Path_Without_ private void Check_Inheritance_Backward_Compatibility(LiquidThemeEngineOptions options) { var shopifyLiquidThemeEngine = GetThemeEngine(true, options); - InitializeStreams(false, false); + InitializeStreams(DefaultThemeType.WithoutPresets, false); var settings = shopifyLiquidThemeEngine.GetSettings(); Assert.False(settings.ContainsKey("background_color")); Assert.Equal("#333", settings["foreground_color"]); @@ -125,21 +158,21 @@ private void Check_Inheritance_Backward_Compatibility(LiquidThemeEngineOptions o [Fact] public void Settings_Inheritance_Both_Are_Flat() { - InitializeStreams(false, false); + InitializeStreams(DefaultThemeType.WithoutPresets, false); Check_Colors_In_Merged_Settings(); } [Fact] public void Settings_Inheritance_Base_Has_Preset_Current_Is_Flat() { - InitializeStreams(true, false); + InitializeStreams(DefaultThemeType.WithPresets, false); Check_Colors_In_Merged_Settings(); } [Fact] public void Settings_Inheritance_Current_Select_Preset_From_Base() { - InitializeStreams(true, true); + InitializeStreams(DefaultThemeType.WithPresets, true); Check_Colors_In_Merged_Settings(true); } @@ -156,9 +189,25 @@ private void Check_Colors_In_Merged_Settings(bool isDarkPreset = false) Assert.Equal("#333", settings["foreground_color"]); } - private void InitializeStreams(bool defaultThemeHasPresets, bool currentThemeHasSelectedPreset) + private void InitializeStreams(DefaultThemeType defaultThemeType, bool currentThemeHasSelectedPreset) { - InitializeStream(_defaultThemeStreamWriter, out var defaultThemeStream, defaultThemeHasPresets ? DefaultSettingsWithPresets : DefaultSettingsWithoutPresets); + JObject defaultThemeJson; + switch (defaultThemeType) + { + case DefaultThemeType.WithoutPresets: + defaultThemeJson = DefaultSettingsWithoutPresets; + break; + case DefaultThemeType.WithPresets: + defaultThemeJson = DefaultSettingsWithPresets; + break; + case DefaultThemeType.WithPresetsAndCurrentObject: + defaultThemeJson = DefaultSettingsWithPresetsAndCurrentObject; + break; + default: + throw new ArgumentOutOfRangeException(nameof(defaultThemeType), defaultThemeType, null); + } + + InitializeStream(_defaultThemeStreamWriter, out var defaultThemeStream, defaultThemeJson); DefaultThemeStream = defaultThemeStream; InitializeStream(_currentThemeStreamWriter, out var currentThemeStream, currentThemeHasSelectedPreset ? CurrentSettingsWithSelectedPreset : CurrentSettingsWithoutSelectedPreset);