private async Task <TestResultViewModel> TestCard(FileViewModel cardFile, FileViewModel hostConfigFile) { var renderResult = await RenderCard(cardFile, hostConfigFile); var result = await TestResultViewModel.CreateAsync( cardFile : cardFile, hostConfigFile : hostConfigFile, renderedTestResult : renderResult.Item1, actualImageFile : renderResult.Item2, actualJsonFile : renderResult.Item3, expectedFolder : _expectedFolder, sourceHostConfigsFolder : _sourceHostConfigsFolder, sourceCardsFolder : _sourceCardsFolder); OnSingleTestCompleted?.Invoke(this, result.Status); return(result); }
private async Task <TestResultViewModel> TestCard(FileViewModel cardFile, FileViewModel hostConfigFile) { Dictionary <string, IAdaptiveCardResourceResolver> resourceResolvers = new Dictionary <string, IAdaptiveCardResourceResolver>(); resourceResolvers.Add("symbol", new SampleResourceResolver()); var renderResult = await RenderCard(cardFile, hostConfigFile, resourceResolvers); var result = await TestResultViewModel.CreateAsync( cardFile : cardFile, hostConfigFile : hostConfigFile, renderedTestResult : renderResult.Item1, actualImageFile : renderResult.Item2, actualJsonFile : renderResult.Item3, expectedFolder : _expectedFolder, sourceHostConfigsFolder : _sourceHostConfigsFolder, sourceCardsFolder : _sourceCardsFolder); OnSingleTestCompleted?.Invoke(this, result.Status); return(result); }
private async Task <TestResultViewModel> TestCard(FileViewModel cardFile, FileViewModel hostConfigFile) { Dictionary <string, IAdaptiveCardResourceResolver> resourceResolvers = new Dictionary <string, IAdaptiveCardResourceResolver>(); resourceResolvers.Add("symbol", new SampleResourceResolver()); uint reruns = 0; TestResultViewModel result = null; bool retryImage = true; while (retryImage) { var renderResult = await RenderCard(cardFile, hostConfigFile, resourceResolvers); result = await TestResultViewModel.CreateAsync( cardFile : cardFile, hostConfigFile : hostConfigFile, renderedTestResult : renderResult.Item1, actualImageFile : renderResult.Item2, actualJsonFile : renderResult.Item3, expectedFolder : _expectedFolder, sourceHostConfigsFolder : _sourceHostConfigsFolder, sourceCardsFolder : _sourceCardsFolder); if (!result.Status.IsPassingStatus()) { // Retry if we failed on image matching for an unchanged card to allow for // occasional differences in image rendering retryImage = result.Status.OriginalMatched && !result.Status.ImageMatched && (reruns < 3); reruns++; } else { retryImage = false; } } OnSingleTestCompleted?.Invoke(this, result.Status); return(result); }
public static async Task <FileViewModel> LoadAsync(StorageFile file) { var answer = new FileViewModel(); const string linkedCardsFolder = "LinkedCards\\"; const string linkedHostConfigsFolder = "LinkedHostConfigs\\"; const string expected = "Expected\\"; const string results = "Results\\"; if (file.Path.Contains(linkedCardsFolder)) { answer.Name = file.Path.Substring(file.Path.IndexOf(linkedCardsFolder) + linkedCardsFolder.Length); } else if (file.Path.Contains(linkedHostConfigsFolder)) { answer.Name = file.Path.Substring(file.Path.IndexOf(linkedHostConfigsFolder) + linkedHostConfigsFolder.Length); } else if (file.Path.Contains(expected)) { answer.Name = file.Path.Substring(file.Path.IndexOf(expected) + expected.Length); } else if (file.Path.Contains(results)) { answer.Name = file.Path.Substring(file.Path.IndexOf(results) + expected.Length); } else { throw new NotImplementedException("Unknown path: " + file.Path); } answer.Contents = await FileIO.ReadTextAsync(file); answer.Contents = answer.Contents.Replace("\r\n", "\n"); answer.Hash = ToSha1(answer.Contents).Substring(0, 7); return(answer); }
private async Task <Tuple <string, StorageFile, StorageFile, UIElement> > RenderCard(FileViewModel cardFile, FileViewModel hostConfigFile) { string error = null; RenderTargetBitmap rtb = null; string roundTrippedJsonString = null; try { AdaptiveHostConfig hostConfig = AdaptiveHostConfig.FromJsonString(hostConfigFile.Contents).HostConfig; if (hostConfig == null) { error = "Parsing hostConfig failed"; } else { AdaptiveCard card = AdaptiveCard.FromJsonString(cardFile.Contents).AdaptiveCard; if (card == null) { error = "Parsing card failed"; } else { roundTrippedJsonString = card.ToJson().ToString(); card = AdaptiveCard.FromJsonString(roundTrippedJsonString).AdaptiveCard; var renderer = new AdaptiveCardRenderer() { HostConfig = hostConfig }; if (hostConfigFile.Name.Contains("windows-timeline")) { renderer.SetFixedDimensions(320, 180); CurrentCardVisualWidth = 320; } else if (hostConfigFile.Name.Contains("windows-live-tile")) { renderer.SetFixedDimensions(310, 310); CurrentCardVisualWidth = 310; } else { CurrentCardVisualWidth = 400; } FrameworkElement xaml = renderer.RenderAdaptiveCard(card).FrameworkElement as FrameworkElement; if (xaml == null) { error = "Rendering card failed"; } else { xaml = new Border() { Background = new SolidColorBrush(Colors.White), Child = xaml, IsHitTestVisible = false // Disable HitTest so that mouse pointer can't accidently hover over a button }; // The theme is important to set since it'll ensure buttons/inputs appear correctly if (hostConfigFile.Name.Contains("windows-notification")) { xaml.RequestedTheme = ElementTheme.Dark; } else { xaml.RequestedTheme = ElementTheme.Light; } CurrentCardVisual = xaml; ExpandShowCards(xaml); NormalizeTimePickers(xaml); await WaitOnAllImagesAsync(xaml); rtb = new RenderTargetBitmap(); await rtb.RenderAsync(CurrentCardVisual); } } } } catch (Exception ex) { error = ex.ToString(); } StorageFile file = null; StorageFile file2 = null; if (error == null) { file = await _tempResultsFolder.CreateFileAsync("Result.png", CreationCollisionOption.GenerateUniqueName); file2 = await _tempResultsFolder.CreateFileAsync("Result.json", CreationCollisionOption.GenerateUniqueName); // https://basquang.wordpress.com/2013/09/26/windows-store-8-1-save-visual-element-to-bitmap-image-file/ var buffer = await rtb.GetPixelsAsync(); using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)rtb.PixelWidth, (uint)rtb.PixelHeight, 96, 96, buffer.ToArray()); // Set the size of the card so that it can be rendered just like the bitmap if (CurrentCardVisual is FrameworkElement fe) { fe.Width = rtb.PixelWidth; fe.Height = rtb.PixelHeight; } await encoder.FlushAsync(); } if (roundTrippedJsonString != null) { await Windows.Storage.FileIO.WriteTextAsync(file2, roundTrippedJsonString); } } return(new Tuple <string, StorageFile, StorageFile, UIElement>(error, file, file2, CurrentCardVisual)); }
private async Task <Tuple <RenderedTestResult, StorageFile, StorageFile> > RenderCard(FileViewModel cardFile, FileViewModel hostConfigFile, Dictionary <string, IAdaptiveCardResourceResolver> resourceResolvers) { var renderResult = await UWPTestLibrary.RenderTestHelpers.RenderCard(cardFile, hostConfigFile, resourceResolvers); UWPTestLibrary.ImageWaiter imageWaiter = new ImageWaiter(renderResult.Tree); CurrentCardVisual = renderResult.Tree; CurrentCardVisualWidth = renderResult.CardWidth; await imageWaiter.WaitOnAllImagesAsync(); StorageFile imageResultFile = null; StorageFile jsonResultFile = null; if (renderResult.Error == null) { imageResultFile = await _tempResultsFolder.CreateFileAsync("Result.png", CreationCollisionOption.GenerateUniqueName); jsonResultFile = await _tempResultsFolder.CreateFileAsync("Result.json", CreationCollisionOption.GenerateUniqueName); await UWPTestLibrary.RenderTestHelpers.ResultsToFile(imageResultFile, jsonResultFile, renderResult.RoundTrippedJSON, CurrentCardVisual); } return(new Tuple <RenderedTestResult, StorageFile, StorageFile>(renderResult, imageResultFile, jsonResultFile)); }
private async Task <Tuple <string, StorageFile, StorageFile, UIElement> > RenderCard(FileViewModel cardFile, FileViewModel hostConfigFile) { var renderResult = await UWPTestLibrary.RenderTestHelpers.RenderCard(cardFile, hostConfigFile); UWPTestLibrary.ImageWaiter imageWaiter = new ImageWaiter(renderResult.Item3); CurrentCardVisual = renderResult.Item3; CurrentCardVisualWidth = renderResult.Item4; await imageWaiter.WaitOnAllImagesAsync(); StorageFile imageResultFile = null; StorageFile jsonResultFile = null; if (renderResult.Item1 == null) { imageResultFile = await _tempResultsFolder.CreateFileAsync("Result.png", CreationCollisionOption.GenerateUniqueName); jsonResultFile = await _tempResultsFolder.CreateFileAsync("Result.json", CreationCollisionOption.GenerateUniqueName); await UWPTestLibrary.RenderTestHelpers.ResultsToFile(imageResultFile, jsonResultFile, renderResult.Item2, CurrentCardVisual); } return(new Tuple <string, StorageFile, StorageFile, UIElement>(renderResult.Item1, imageResultFile, jsonResultFile, CurrentCardVisual)); }
public static async Task <TestResultViewModel> CreateAsync( FileViewModel cardFile, FileViewModel hostConfigFile, string actualError, StorageFile actualImageFile, StorageFolder expectedFolder, StorageFolder sourceHostConfigsFolder, StorageFolder sourceCardsFolder, UIElement xamlCard) { var answer = new TestResultViewModel() { CardName = cardFile.Name, CardFile = cardFile, XamlCard = xamlCard, HostConfigName = hostConfigFile.Name, HostConfigFile = hostConfigFile, ActualError = actualError, ActualImageFile = actualImageFile, _expectedFolder = expectedFolder, _sourceHostConfigsFolder = sourceHostConfigsFolder, _sourceCardsFolder = sourceCardsFolder, _expectedFileNameWithoutExtension = GetStrippedFileName(hostConfigFile) + "." + GetStrippedFileName(cardFile) }; try { var storedInfo = await StoredTestResultInfo.DeserializeFromFileAsync(expectedFolder, answer._expectedFileNameWithoutExtension); if (storedInfo == null) { answer.Status = TestStatus.New; } else { answer._oldHostConfigHash = storedInfo.HostConfigHash; answer._oldCardHash = storedInfo.CardHash; if (storedInfo.Error != null) { answer.ExpectedError = storedInfo.Error; } else { answer.ExpectedImageFile = await expectedFolder.GetFileAsync(answer._expectedFileNameWithoutExtension + ".png"); } } // If both had error, compare via the error if (answer.ExpectedError != null && answer.ActualError != null) { if (answer.ExpectedError == answer.ActualError) { answer.Status = TestStatus.Passed; } else { answer.Status = TestStatus.Failed; } } // If neither had error, compare via the image else if (answer.ExpectedImageFile != null && answer.ActualImageFile != null) { byte[] oldBytes = await GetPixelDataBytesAsync(answer.ExpectedImageFile); byte[] newBytes = await GetPixelDataBytesAsync(answer.ActualImageFile); if (ImageBytesAreTheSame(oldBytes, newBytes)) { answer.Status = TestStatus.Passed; } else { answer.Status = TestStatus.Failed; } } // Otherwise one had image and one had error, so fail else { answer.Status = TestStatus.Failed; } // See if the source chagned by checking // if the hashes have changed since the stored info if (storedInfo.HostConfigHash != hostConfigFile.Hash || storedInfo.CardHash != cardFile.Hash) { answer.Status = (answer.Status == TestStatus.Failed) ? TestStatus.FailedButSourceWasChanged : TestStatus.PassedButSourceWasChanged; } } catch { // Any exceptions being thrown get reported as "New", typically this results from file // not found of an expected file, which means it genuinely is new answer.Status = TestStatus.New; } return(answer); }
private static string GetStrippedFileName(FileViewModel file) { return(GetStrippedFileName(file.Name)); }