diff --git a/ClosedXML_Tests/ClosedXML_Tests.csproj b/ClosedXML_Tests/ClosedXML_Tests.csproj index dc1183d..a2e2d37 100644 --- a/ClosedXML_Tests/ClosedXML_Tests.csproj +++ b/ClosedXML_Tests/ClosedXML_Tests.csproj @@ -310,6 +310,8 @@ + + diff --git a/ClosedXML_Tests/Excel/Styles/XLFillTests.cs b/ClosedXML_Tests/Excel/Styles/XLFillTests.cs index 72abc22..87fbb2f 100644 --- a/ClosedXML_Tests/Excel/Styles/XLFillTests.cs +++ b/ClosedXML_Tests/Excel/Styles/XLFillTests.cs @@ -1,5 +1,6 @@ using ClosedXML.Excel; using NUnit.Framework; +using System.IO; namespace ClosedXML_Tests.Excel { @@ -12,30 +13,30 @@ [Test] public void BackgroundColorSetsPattern() { - var fill = new XLFill {BackgroundColor = XLColor.Blue}; + var fill = new XLFill { BackgroundColor = XLColor.Blue }; Assert.AreEqual(XLFillPatternValues.Solid, fill.PatternType); } [Test] public void BackgroundNoColorSetsPatternNone() { - var fill = new XLFill {BackgroundColor = XLColor.NoColor}; + var fill = new XLFill { BackgroundColor = XLColor.NoColor }; Assert.AreEqual(XLFillPatternValues.None, fill.PatternType); } [Test] public void BackgroundPatternEqualCheck() { - var fill1 = new XLFill {BackgroundColor = XLColor.Blue}; - var fill2 = new XLFill {BackgroundColor = XLColor.Blue}; + var fill1 = new XLFill { BackgroundColor = XLColor.Blue }; + var fill2 = new XLFill { BackgroundColor = XLColor.Blue }; Assert.IsTrue(fill1.Equals(fill2)); } [Test] public void BackgroundPatternNotEqualCheck() { - var fill1 = new XLFill {BackgroundColor = XLColor.Blue}; - var fill2 = new XLFill {BackgroundColor = XLColor.Red}; + var fill1 = new XLFill { BackgroundColor = XLColor.Blue }; + var fill2 = new XLFill { BackgroundColor = XLColor.Red }; Assert.IsFalse(fill1.Equals(fill2)); } @@ -61,5 +62,20 @@ Assert.AreEqual(style.Border.LeftBorderColor, XLColor.Blue); Assert.AreEqual(style.Border.RightBorderColor, XLColor.Blue); } + + [Test] + public void LoadAndSaveTransparentBackgroundFill() + { + using (var stream = TestHelper.GetStreamFromResource(TestHelper.GetResourcePath(@"StyleReferenceFiles\TransparentBackgroundFill\inputfile.xlsx"))) + using (var ms = new MemoryStream()) + { + TestHelper.CreateAndCompare(() => + { + var wb = new XLWorkbook(stream); + wb.SaveAs(ms); + return wb; + }, @"StyleReferenceFiles\TransparentBackgroundFill\TransparentBackgroundFill.xlsx"); + } + } } } diff --git a/ClosedXML_Tests/Resource/StyleReferenceFiles/TransparentBackgroundFill/TransparentBackgroundFill.xlsx b/ClosedXML_Tests/Resource/StyleReferenceFiles/TransparentBackgroundFill/TransparentBackgroundFill.xlsx new file mode 100644 index 0000000..3a12637 --- /dev/null +++ b/ClosedXML_Tests/Resource/StyleReferenceFiles/TransparentBackgroundFill/TransparentBackgroundFill.xlsx Binary files differ diff --git a/ClosedXML_Tests/Resource/StyleReferenceFiles/TransparentBackgroundFill/inputfile.xlsx b/ClosedXML_Tests/Resource/StyleReferenceFiles/TransparentBackgroundFill/inputfile.xlsx new file mode 100644 index 0000000..6d6f1a8 --- /dev/null +++ b/ClosedXML_Tests/Resource/StyleReferenceFiles/TransparentBackgroundFill/inputfile.xlsx Binary files differ diff --git a/ClosedXML_Tests/TestHelper.cs b/ClosedXML_Tests/TestHelper.cs index 646d9d0..5c1acf8 100644 --- a/ClosedXML_Tests/TestHelper.cs +++ b/ClosedXML_Tests/TestHelper.cs @@ -22,16 +22,17 @@ { get { - return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + return Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Generated"); } } public const string ActualTestResultPostFix = ""; - public static readonly string TestsExampleOutputDirectory = Path.Combine(TestsOutputDirectory, "Examples"); + public static readonly string ExampleTestsOutputDirectory = Path.Combine(TestsOutputDirectory, "Examples"); + public static readonly string OtherTestsOutputDirectory = Path.Combine(TestsOutputDirectory, "Other"); private const bool CompareWithResources = true; - private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(null, ".Resource.Examples."); + private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(null, ".Resource."); public static void SaveWorkbook(XLWorkbook workbook, params string[] fileNameParts) { @@ -59,7 +60,7 @@ var example = new T(); string[] pathParts = filePartName.Split(new char[] { '\\' }); - string filePath1 = Path.Combine(new List() { TestsExampleOutputDirectory }.Concat(pathParts).ToArray()); + string filePath1 = Path.Combine(new List() { ExampleTestsOutputDirectory }.Concat(pathParts).ToArray()); var extension = Path.GetExtension(filePath1); var directory = Path.GetDirectoryName(filePath1); @@ -76,9 +77,46 @@ wb.SaveAs(filePath2, true, evaluateFormulae); if (CompareWithResources) - { - string resourcePath = filePartName.Replace('\\', '.').TrimStart('.'); + string resourcePath = "Examples." + filePartName.Replace('\\', '.').TrimStart('.'); + using (var streamExpected = _extractor.ReadFileFromResToStream(resourcePath)) + using (var streamActual = File.OpenRead(filePath2)) + { + string message; + var success = ExcelDocsComparer.Compare(streamActual, streamExpected, TestHelper.IsRunningOnUnix, out message); + var formattedMessage = + String.Format( + "Actual file '{0}' is different than the expected file '{1}'. The difference is: '{2}'", + filePath2, resourcePath, message); + + Assert.IsTrue(success, formattedMessage); + } + } + } + + public static void CreateAndCompare(Func workbookGenerator, string referenceResource, bool evaluateFormulae = false) + { + Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US"); + + string[] pathParts = referenceResource.Split(new char[] { '\\' }); + string filePath1 = Path.Combine(new List() { OtherTestsOutputDirectory }.Concat(pathParts).ToArray()); + + var extension = Path.GetExtension(filePath1); + var directory = Path.GetDirectoryName(filePath1); + + var fileName = Path.GetFileNameWithoutExtension(filePath1); + fileName += ActualTestResultPostFix; + fileName = Path.ChangeExtension(fileName, extension); + + filePath1 = Path.Combine(directory, "z" + fileName); + var filePath2 = Path.Combine(directory, fileName); + + using (var wb = workbookGenerator.Invoke()) + wb.SaveAs(filePath2, true, evaluateFormulae); + + if (CompareWithResources) + { + string resourcePath = referenceResource.Replace('\\', '.').TrimStart('.'); using (var streamExpected = _extractor.ReadFileFromResToStream(resourcePath)) using (var streamActual = File.OpenRead(filePath2)) { diff --git a/ClosedXML_Tests/Utils/PackageHelper.cs b/ClosedXML_Tests/Utils/PackageHelper.cs index 3def760..60bc482 100644 --- a/ClosedXML_Tests/Utils/PackageHelper.cs +++ b/ClosedXML_Tests/Utils/PackageHelper.cs @@ -89,7 +89,7 @@ throw new ArgumentNullException("dest"); } - #endregion + #endregion Check if (dest.PartExists(uri)) { @@ -130,7 +130,7 @@ throw new ArgumentNullException("serializeAction"); } - #endregion + #endregion Check if (package.PartExists(descriptor.Uri)) { @@ -160,7 +160,7 @@ throw new ArgumentNullException("serializeAction"); } - #endregion + #endregion Check if (package.PartExists(descriptor.Uri)) { @@ -190,7 +190,7 @@ throw new ArgumentNullException("deserializeFunc"); } - #endregion + #endregion Check if (!package.PartExists(uri)) { @@ -220,7 +220,7 @@ throw new ArgumentNullException("deserializeAction"); } - #endregion + #endregion Check if (!package.PartExists(uri)) { @@ -250,7 +250,7 @@ throw new ArgumentNullException("deserializeAction"); } - #endregion + #endregion Check if (!package.PartExists(uri)) { @@ -301,7 +301,7 @@ throw new ArgumentNullException("right"); } - #endregion + #endregion Check excludeMethod = excludeMethod ?? (uri => false); PackagePartCollection leftParts = left.GetParts(); @@ -353,7 +353,10 @@ leftPart.ContentType == @"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" && rightPart.ContentType == @"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"; - if (!StreamHelper.Compare(oneStream, otherStream, stripColumnWidthsFromSheet)) + var tuple1 = new Tuple(pair.Uri, oneStream); + var tuple2 = new Tuple(pair.Uri, otherStream); + + if (!StreamHelper.Compare(tuple1, tuple2, stripColumnWidthsFromSheet)) { pair.Status = CompareStatus.NonEqual; if (compareToFirstDifference) @@ -387,11 +390,16 @@ { #region Private fields - [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly CompressionOption _compressOption; - [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly string _contentType; - [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Uri _uri; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly CompressionOption _compressOption; - #endregion + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly string _contentType; + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly Uri _uri; + + #endregion Private fields #region Constructor @@ -414,33 +422,36 @@ throw new ArgumentNullException("contentType"); } - #endregion + #endregion Check _uri = uri; _contentType = contentType; _compressOption = compressOption; } - #endregion + #endregion Constructor #region Public properties public Uri Uri { - [DebuggerStepThrough] get { return _uri; } + [DebuggerStepThrough] + get { return _uri; } } public string ContentType { - [DebuggerStepThrough] get { return _contentType; } + [DebuggerStepThrough] + get { return _contentType; } } public CompressionOption CompressOption { - [DebuggerStepThrough] get { return _compressOption; } + [DebuggerStepThrough] + get { return _compressOption; } } - #endregion + #endregion Public properties #region Public methods @@ -449,10 +460,10 @@ return string.Format("Uri:{0} ContentType: {1}, Compression: {2}", _uri, _contentType, _compressOption); } - #endregion + #endregion Public methods } - #endregion + #endregion Nested type: PackagePartDescriptor #region Nested type: CompareStatus @@ -464,7 +475,7 @@ NonEqual } - #endregion + #endregion Nested type: CompareStatus #region Nested type: PartPair @@ -472,10 +483,13 @@ { #region Private fields - [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Uri _uri; - [DebuggerBrowsable(DebuggerBrowsableState.Never)] private CompareStatus _status; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly Uri _uri; - #endregion + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private CompareStatus _status; + + #endregion Private fields #region Constructor @@ -485,26 +499,29 @@ _status = status; } - #endregion + #endregion Constructor #region Public properties public Uri Uri { - [DebuggerStepThrough] get { return _uri; } + [DebuggerStepThrough] + get { return _uri; } } public CompareStatus Status { - [DebuggerStepThrough] get { return _status; } - [DebuggerStepThrough] set { _status = value; } + [DebuggerStepThrough] + get { return _status; } + [DebuggerStepThrough] + set { _status = value; } } - #endregion + #endregion Public properties } - #endregion + #endregion Nested type: PartPair //-- } -} \ No newline at end of file +} diff --git a/ClosedXML_Tests/Utils/StreamHelper.cs b/ClosedXML_Tests/Utils/StreamHelper.cs index 8ecb4f9..bf89911 100644 --- a/ClosedXML_Tests/Utils/StreamHelper.cs +++ b/ClosedXML_Tests/Utils/StreamHelper.cs @@ -114,36 +114,39 @@ /// /// /// /// - public static bool Compare(Stream one, Stream other, bool stripColumnWidths) + public static bool Compare(Tuple tuple1, Tuple tuple2, bool stripColumnWidths) { #region Check - if (one == null) + if (tuple1 == null || tuple1.Item1 == null || tuple1.Item2 == null) { throw new ArgumentNullException("one"); } - if (other == null) + if (tuple2 == null || tuple2.Item1 == null || tuple2.Item2 == null) { throw new ArgumentNullException("other"); } - if (one.Position != 0) + if (tuple1.Item2.Position != 0) { throw new ArgumentException("Must be in position 0", "one"); } - if (other.Position != 0) + if (tuple1.Item2.Position != 0) { throw new ArgumentException("Must be in position 0", "other"); } #endregion Check - var stringOne = new StreamReader(one).ReadToEnd().RemoveIgnoredParts(stripColumnWidths, ignoreGuids: true); - var stringOther = new StreamReader(other).ReadToEnd().RemoveIgnoredParts(stripColumnWidths, ignoreGuids: true); + var stringOne = new StreamReader(tuple1.Item2).ReadToEnd().RemoveIgnoredParts(tuple1.Item1, stripColumnWidths, ignoreGuids: true); + var stringOther = new StreamReader(tuple2.Item2).ReadToEnd().RemoveIgnoredParts(tuple2.Item1, stripColumnWidths, ignoreGuids: true); return stringOne == stringOther; } - private static string RemoveIgnoredParts(this string s, Boolean ignoreColumnWidths, Boolean ignoreGuids) + private static string RemoveIgnoredParts(this string s, Uri uri, Boolean ignoreColumnWidths, Boolean ignoreGuids) { + foreach (var pair in uriSpecificIgnores.Where(p => p.Key.Equals(uri.OriginalString))) + s = pair.Value.Replace(s, ""); + if (ignoreColumnWidths) s = RemoveColumnWidths(s); @@ -153,6 +156,12 @@ return s; } + private static IEnumerable> uriSpecificIgnores = new List>() + { + // Remove dcterms elements + new KeyValuePair("/docProps/core.xml", new Regex(@"", RegexOptions.Compiled)) + }; + private static Regex columnRegex = new Regex("", RegexOptions.Compiled); private static Regex widthRegex = new Regex("width=\"\\d+(\\.\\d+)?\"\\s+", RegexOptions.Compiled);