// Copyright (c) Brice Lambson // The Brice Lambson licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/ using System.Collections.Specialized; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Text.Json; using ImageResizer.Models; using ImageResizer.Test; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace ImageResizer.Properties { [TestClass] public class SettingsTests { private static App _imageResizerApp; public SettingsTests() { // Change settings.json path to a temp file Settings.SettingsPath = ".\\test_settings.json"; } [ClassInitialize] #pragma warning disable CA1801 // Review unused parameters public static void ClassInitialize(TestContext context) #pragma warning restore CA1801 // Review unused parameters { // new App() needs to be created since Settings.Reload() uses App.Current to update properties on the UI thread. App() can be created only once otherwise it results in System.InvalidOperationException : Cannot create more than one System.Windows.Application instance in the same AppDomain. _imageResizerApp = new App(); } [TestMethod] public void AllSizesPropagatesSizesCollectionEvents() { var settings = new Settings { CustomSize = new CustomSize(), }; settings.Sizes.Clear(); var ncc = (INotifyCollectionChanged)settings.AllSizes; var result = AssertEx.Raises( h => ncc.CollectionChanged += h, h => ncc.CollectionChanged -= h, () => settings.Sizes.Add(new ResizeSize())); Assert.AreEqual(NotifyCollectionChangedAction.Add, result.Arguments.Action); } [TestMethod] public void AllSizesPropagatesSizesPropertyEvents() { var settings = new Settings { CustomSize = new CustomSize(), }; settings.Sizes.Clear(); var result = false; ((INotifyPropertyChanged)settings.AllSizes).PropertyChanged += (sender, e) => { if (e.PropertyName == "Item[]") { result = true; } }; settings.Sizes.Add(new ResizeSize()); Assert.IsTrue(result); } [TestMethod] public void AllSizesContainsSizes() { var settings = new Settings { CustomSize = new CustomSize(), }; settings.Sizes.Add(new ResizeSize()); CollectionAssert.Contains(settings.AllSizes.ToList(), settings.Sizes[0]); } [TestMethod] public void AllSizesContainsCustomSize() { var settings = new Settings { CustomSize = new CustomSize(), }; settings.Sizes.Clear(); CollectionAssert.Contains(settings.AllSizes.ToList(), settings.CustomSize); } [TestMethod] public void AllSizesHandlesPropertyEventsForCustomSize() { var originalCustomSize = new CustomSize(); var settings = new Settings { CustomSize = originalCustomSize, }; settings.Sizes.Clear(); var ncc = (INotifyCollectionChanged)settings.AllSizes; var result = AssertEx.Raises( h => ncc.CollectionChanged += h, h => ncc.CollectionChanged -= h, () => settings.CustomSize = new CustomSize()); Assert.AreEqual(NotifyCollectionChangedAction.Replace, result.Arguments.Action); Assert.AreEqual(1, result.Arguments.NewItems.Count); Assert.AreEqual(settings.CustomSize, result.Arguments.NewItems[0]); Assert.AreEqual(0, result.Arguments.NewStartingIndex); Assert.AreEqual(1, result.Arguments.OldItems.Count); Assert.AreEqual(originalCustomSize, result.Arguments.OldItems[0]); Assert.AreEqual(0, result.Arguments.OldStartingIndex); } [TestMethod] public void FileNameFormatWorks() { var settings = new Settings { FileName = "{T}%1e%2s%3t%4%5%6%7" }; var result = settings.FileNameFormat; Assert.AreEqual("{{T}}{0}e{1}s{2}t{3}{4}{5}%7", result); } [DataTestMethod] [DataRow(0)] [DataRow(1)] [DataRow(2)] public void SelectedSizeReturnsCustomSizeWhenOutOfRange(int index) { var settings = new Settings { SelectedSizeIndex = index, CustomSize = new CustomSize(), }; settings.Sizes.Clear(); var result = settings.SelectedSize; Assert.AreEqual(settings.CustomSize, result); } [TestMethod] public void SelectedSizeReturnsSizeWhenInRange() { var settings = new Settings { SelectedSizeIndex = 0, }; settings.Sizes.Add(new ResizeSize()); var result = settings.SelectedSize; Assert.AreEqual(settings.Sizes[0], result); } [TestMethod] public void IDataErrorInfoErrorReturnsEmpty() { var settings = new Settings(); var result = ((IDataErrorInfo)settings).Error; Assert.AreEqual(result, string.Empty); } [DataTestMethod] [DataRow(0)] [DataRow(101)] public void IDataErrorInfoItemJpegQualityLevelReturnsErrorWhenOutOfRange(int value) { var settings = new Settings { JpegQualityLevel = value }; var result = ((IDataErrorInfo)settings)["JpegQualityLevel"]; // Using InvariantCulture since this is used internally Assert.AreEqual( string.Format(CultureInfo.InvariantCulture, Resources.ValueMustBeBetween, 1, 100), result); } [DataTestMethod] [DataRow(1)] [DataRow(100)] public void IDataErrorInfoItemJpegQualityLevelReturnsEmptyWhenInRange(int value) { var settings = new Settings { JpegQualityLevel = value }; var result = ((IDataErrorInfo)settings)["JpegQualityLevel"]; Assert.AreEqual(result, string.Empty); } [TestMethod] public void IDataErrorInfoItemReturnsEmptyWhenNotJpegQualityLevel() { var settings = new Settings(); var result = ((IDataErrorInfo)settings)["Unknown"]; Assert.AreEqual(result, string.Empty); } [TestMethod] public void ReloadCreatesFileWhenFileNotFound() { // Arrange var settings = new Settings(); // Assert Assert.IsFalse(System.IO.File.Exists(Settings.SettingsPath)); // Act settings.Reload(); // Assert Assert.IsTrue(System.IO.File.Exists(Settings.SettingsPath)); } [TestMethod] public void SaveCreatesFile() { // Arrange var settings = new Settings(); // Assert Assert.IsFalse(System.IO.File.Exists(Settings.SettingsPath)); // Act settings.Save(); // Assert Assert.IsTrue(System.IO.File.Exists(Settings.SettingsPath)); } [TestMethod] public void SaveJsonIsReadableByReload() { // Arrange var settings = new Settings(); // Assert Assert.IsFalse(System.IO.File.Exists(Settings.SettingsPath)); // Act settings.Save(); settings.Reload(); // If the JSON file created by Save() is not readable this function will throw an error // Assert Assert.IsTrue(System.IO.File.Exists(Settings.SettingsPath)); } [TestMethod] public void ReloadRaisesPropertyChanged() { // Arrange var settings = new Settings(); settings.Save(); // To create the settings file var shrinkOnlyChanged = false; var replaceChanged = false; var ignoreOrientationChanged = false; var jpegQualityLevelChanged = false; var pngInterlaceOptionChanged = false; var tiffCompressOptionChanged = false; var fileNameChanged = false; var keepDateModifiedChanged = false; var fallbackEncoderChanged = false; var customSizeChanged = false; var selectedSizeIndexChanged = false; settings.PropertyChanged += (sender, e) => { if (e.PropertyName == "ShrinkOnly") { shrinkOnlyChanged = true; } else if (e.PropertyName == "Replace") { replaceChanged = true; } else if (e.PropertyName == "IgnoreOrientation") { ignoreOrientationChanged = true; } else if (e.PropertyName == "JpegQualityLevel") { jpegQualityLevelChanged = true; } else if (e.PropertyName == "PngInterlaceOption") { pngInterlaceOptionChanged = true; } else if (e.PropertyName == "TiffCompressOption") { tiffCompressOptionChanged = true; } else if (e.PropertyName == "FileName") { fileNameChanged = true; } else if (e.PropertyName == "KeepDateModified") { keepDateModifiedChanged = true; } else if (e.PropertyName == "FallbackEncoder") { fallbackEncoderChanged = true; } else if (e.PropertyName == "CustomSize") { customSizeChanged = true; } else if (e.PropertyName == "SelectedSizeIndex") { selectedSizeIndexChanged = true; } }; // Act settings.Reload(); // Assert Assert.IsTrue(shrinkOnlyChanged); Assert.IsTrue(replaceChanged); Assert.IsTrue(ignoreOrientationChanged); Assert.IsTrue(jpegQualityLevelChanged); Assert.IsTrue(pngInterlaceOptionChanged); Assert.IsTrue(tiffCompressOptionChanged); Assert.IsTrue(fileNameChanged); Assert.IsTrue(keepDateModifiedChanged); Assert.IsTrue(fallbackEncoderChanged); Assert.IsTrue(customSizeChanged); Assert.IsTrue(selectedSizeIndexChanged); } [TestMethod] public void SystemTextJsonDeserializesCorrectly() { // Generated Settings file in 0.72 var defaultInput = "{\r\n \"properties\": {\r\n \"imageresizer_selectedSizeIndex\": {\r\n \"value\": 1\r\n },\r\n \"imageresizer_shrinkOnly\": {\r\n \"value\": true\r\n },\r\n \"imageresizer_replace\": {\r\n \"value\": true\r\n },\r\n \"imageresizer_ignoreOrientation\": {\r\n \"value\": false\r\n },\r\n \"imageresizer_jpegQualityLevel\": {\r\n \"value\": 91\r\n },\r\n \"imageresizer_pngInterlaceOption\": {\r\n \"value\": 1\r\n },\r\n \"imageresizer_tiffCompressOption\": {\r\n \"value\": 1\r\n },\r\n \"imageresizer_fileName\": {\r\n \"value\": \"%1 %1 (%2)\"\r\n },\r\n \"imageresizer_sizes\": {\r\n \"value\": [\r\n {\r\n \"Id\": 0,\r\n \"ExtraBoxOpacity\": 100,\r\n \"EnableEtraBoxes\": true,\r\n \"name\": \"Small-NotDefault\",\r\n \"fit\": 1,\r\n \"width\": 854,\r\n \"height\": 480,\r\n \"unit\": 3\r\n },\r\n {\r\n \"Id\": 3,\r\n \"ExtraBoxOpacity\": 100,\r\n \"EnableEtraBoxes\": true,\r\n \"name\": \"Phone\",\r\n \"fit\": 1,\r\n \"width\": 320,\r\n \"height\": 568,\r\n \"unit\": 3\r\n }\r\n ]\r\n },\r\n \"imageresizer_keepDateModified\": {\r\n \"value\": false\r\n },\r\n \"imageresizer_fallbackEncoder\": {\r\n \"value\": \"19e4a5aa-5662-4fc5-a0c0-1758028e1057\"\r\n },\r\n \"imageresizer_customSize\": {\r\n \"value\": {\r\n \"Id\": 4,\r\n \"ExtraBoxOpacity\": 100,\r\n \"EnableEtraBoxes\": true,\r\n \"name\": \"custom\",\r\n \"fit\": 1,\r\n \"width\": 1024,\r\n \"height\": 640,\r\n \"unit\": 3\r\n }\r\n }\r\n },\r\n \"name\": \"Image Resizer\",\r\n \"version\": \"1\"\r\n}"; // Execute readFile/writefile twice and see if serialized string is still correct var resultWrapper = JsonSerializer.Deserialize(defaultInput); var serializedInput = JsonSerializer.Serialize(resultWrapper, new JsonSerializerOptions() { WriteIndented = true }); var resultWrapper2 = JsonSerializer.Deserialize(serializedInput); var serializedInput2 = JsonSerializer.Serialize(resultWrapper2, new JsonSerializerOptions() { WriteIndented = true }); Assert.AreEqual(serializedInput, serializedInput2); Assert.AreEqual("Image Resizer", resultWrapper2.Name); Assert.AreEqual("1", resultWrapper2.Version); Assert.IsNotNull(resultWrapper2.Properties); Assert.IsTrue(resultWrapper2.Properties.ShrinkOnly); Assert.IsTrue(resultWrapper2.Properties.Replace); Assert.AreEqual(91, resultWrapper2.Properties.JpegQualityLevel); Assert.AreEqual(1, (int)resultWrapper2.Properties.PngInterlaceOption); Assert.AreEqual(1, (int)resultWrapper2.Properties.TiffCompressOption); Assert.AreEqual("%1 %1 (%2)", resultWrapper2.Properties.FileName); Assert.AreEqual(2, resultWrapper2.Properties.Sizes.Count); Assert.IsFalse(resultWrapper2.Properties.KeepDateModified); Assert.AreEqual("Small-NotDefault", resultWrapper2.Properties.Sizes[0].Name); } [ClassCleanup] public static void ClassCleanup() { _imageResizerApp.Dispose(); _imageResizerApp = null; } [TestCleanup] public void TestCleanUp() { if (System.IO.File.Exists(Settings.SettingsPath)) { System.IO.File.Delete(Settings.SettingsPath); } } } }