コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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));
        }
コード例 #6
0
        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));
        }
コード例 #7
0
        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));
        }
コード例 #8
0
        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);
        }
コード例 #9
0
 private static string GetStrippedFileName(FileViewModel file)
 {
     return(GetStrippedFileName(file.Name));
 }