using Centron.DAO; using Centron.Data.WebServices.Sales.Receipts; using Centron.Tests.EndToEnd.Infrastructure.Verifier; using DevExpress.CodeParser; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Windows.Forms; using Xunit; using Centron.Core; using Centron.Core.Utils; using DevExpress.Spreadsheet; namespace Centron.Tests.EndToEnd.Infrastructure.Verifier { public class CentronVerifier { public CentronVerifier() { this.Settings = new CentronVerifierSettings(); this.Settings.IgnoreProperty(f => f.CreatedThroughApplicationVersion); this.Settings.IgnoreProperty(f => f.ChangedThroughApplicationVersion); } public CentronVerifierSettings Settings { get; } public bool OverrideExpectedFiles { get; set; } public void VerifyTable(string name, string tableName, string where = null, CentronVerifierSettings settings = null, [CallerFilePath] string sourceFile = "") { where = where ?? "1 = 1"; string sqlStatement = $"SELECT * FROM {tableName} WHERE {where}"; this.VerifySql(name, sqlStatement, settings, sourceFile); } public void VerifySql(string name, string sqlStatement, CentronVerifierSettings settings = null, [CallerFilePath] string sourceFile = "") { using (var session = new DAOSession()) { var table = session.Advanced.RawSqlAccess.GetRawSqlResult(sqlStatement); this.Verify(name, table, settings, sourceFile: sourceFile); } } public void VerifyExcel(string fileName, byte[] excel, [CallerFilePath] string sourceFile = "") { var workbook = new Workbook(); workbook.LoadDocument(excel); var worksheet = workbook.Worksheets[0]; string[,] excelCellValues = new string[worksheet.Rows.LastUsedIndex + 1, worksheet.Columns.LastUsedIndex + 1]; for (int i = 0; i <= worksheet.Rows.LastUsedIndex; i++) for (int j = 0; j <= worksheet.Columns.LastUsedIndex; j++) { var testCell = worksheet.Cells[i, j].Value.ToString(); excelCellValues[i, j] = testCell; } this.Verify(fileName, excelCellValues, sourceFile: sourceFile); } public void Verify(string name, object data, CentronVerifierSettings settings = null, [CallerFilePath] string sourceFile = "") { Guard.NotNullOrWhiteSpace(name, nameof(name)); //data can be NULL //differentPerTargetFramework can be anything //settings can be NULL Guard.NotNullOrWhiteSpace(sourceFile, nameof(sourceFile)); if (settings != null) { settings.MergeWith(this.Settings); } else { settings = this.Settings; } var json = this.SerializeAsJson(data, settings); var expectedFileName = this.GetExpectedFileName(name, sourceFile); var actualFileName = this.GetActualFileName(name, sourceFile); var directory = Path.GetDirectoryName(expectedFileName); if (Directory.Exists(directory) == false) Directory.CreateDirectory(directory); if (this.OverrideExpectedFiles) { File.WriteAllText(expectedFileName, json, Encoding.UTF8); return; } File.WriteAllText(actualFileName, json, Encoding.UTF8); var expected = File.Exists(expectedFileName) ? File.ReadAllText(expectedFileName, Encoding.UTF8) : string.Empty; expected = expected.Replace(@"\r", @""); json = json.Replace(@"\r", @""); try { Assert.Equal(expected, json, ignoreLineEndingDifferences:true); } catch (Exception e) { if(Debugger.IsAttached) this.StartDiffTool(expectedFileName, actualFileName); Console.WriteLine(json); throw new Exception(name + " failed", e); } } private string SerializeAsJson(object data, CentronVerifierSettings verifierSettings) { var settings = new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented, Converters = new List { verifierSettings.CleanupGuidValues ? new CleanupValuesConverter() : null, verifierSettings.CleanupDateTimeValues ? new CleanupValuesConverter(new DateTimeEqualityComparer()) : null, verifierSettings.CleanupDateTimeOffsetValues ? new CleanupValuesConverter(new DateTimeOffsetEqualityComparer()) : null, } .Where(f => f != null) .ToList(), ContractResolver = verifierSettings.GetContractResolver(), }; var ignoredColumns = verifierSettings.GetIgnoredColumns(); if (ignoredColumns.Any() && data is DataTable table) { foreach (var ignoredColumn in ignoredColumns) { if (table.Columns.Contains(ignoredColumn)) table.Columns.Remove(ignoredColumn); } } var serializer = JsonSerializer.Create(settings); var builder = new StringBuilder(); using (var stringWriter = new StringWriter(builder)) using (var writer = new JsonTextWriter(stringWriter) { QuoteChar = '\'', QuoteName = false }) { serializer.Serialize(writer, data); } builder.Replace(@"\\", @"\"); return builder.ToString(); } private string GetExpectedFileName(string name, string sourceFile) { return $"{Path.GetDirectoryName(sourceFile)}/{name}.expected.txt"; } private string GetActualFileName(string name, string sourceFile) { return $"{Path.GetDirectoryName(sourceFile)}/{name}.actual.txt"; } private void StartDiffTool(string expectedFileName, string actualFileName) { try { if (File.Exists(expectedFileName) == false || File.Exists(actualFileName) == false) return; string vsPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe"; if (File.Exists(vsPath)) ProcessHelper.Start(vsPath, $"/diff \"{actualFileName}\" \"{expectedFileName}\""); else ProcessHelper.Start("code", $"--diff \"{actualFileName}\" \"{expectedFileName}\""); } catch (Exception) { //Ooops } } } }