TestStack White doesn't find TextBox in WPF Application

戏子无情 提交于 2019-12-08 06:24:14

问题


I use TestStack White framework to automate testing of a WPF Application It needs to open modal window and access TextBox in it. Everything works well, but White can't find Textbox, although it finds other elements of window

I tried the following lines of code:

TestStack.White.UIItems.TextBox TextBox = CreateBranch.Get<TestStack.White.UIItems.TextBox>(SearchCriteria.byAutomationId("Title"));

where CreateBranch is modal window

I also tried (SearchCriteria.All), (SearchCriteria.ByControlType) and nothing works

Coded UI tool finds this element well by AutomationID, but I need to do it in White

UISpy and other similar tools recognize this control and see its AutomationID

This textbox is custom control, here's code for it, I changed namespace name for privacy:

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace Test.Wpf.Controls.XTextBox
{
    [TemplatePart(Name = "PART_Watermark", Type = typeof(TextBlock))]
    [TemplatePart(Name = "PART_Pasword", Type = typeof(TextBlock))]
    public class XTextBox : TextBox
    {
        #region Static
        static XTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(XTextBox), new FrameworkPropertyMetadata(typeof(XTextBox)));
        }
        #endregion //Static

        #region Fields

        private TextBlock PART_Watermark;
        private TextBlock PART_Pasword;

        #endregion //Fields

        #region DependencyProperties

        public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
            "Watermark",
            typeof(String),
            typeof(XTextBox),
            new PropertyMetadata(String.Empty));

        public static readonly DependencyProperty WatermarkVerticalAlignmentProperty = DependencyProperty.Register(
            "WatermarkVerticalAlignment",
            typeof(VerticalAlignment),
            typeof(XTextBox),
            new PropertyMetadata(VerticalAlignment.Stretch));

        public static readonly DependencyProperty WatermarkForegroundProperty = DependencyProperty.Register(
           "WatermarkForeground",
           typeof(Brush),
           typeof(XTextBox),
           new PropertyMetadata(new SolidColorBrush(Colors.Black)));

        public static readonly DependencyProperty WatermarkFontSizeProperty = DependencyProperty.Register(
           "WatermarkFontSize",
           typeof(Double),
           typeof(XTextBox),
           new PropertyMetadata(12.0));

        public static readonly DependencyProperty IsFloatingProperty = DependencyProperty.Register(
            "IsFloating",
            typeof(Boolean),
            typeof(XTextBox),
            new PropertyMetadata(false));

        public static readonly DependencyProperty IsAccessNegativeProperty = DependencyProperty.Register(
            "IsAccessNegative",
            typeof(Boolean),
            typeof(XTextBox),
            new PropertyMetadata(true));

        public static readonly DependencyProperty IsDigitOnlyProperty = DependencyProperty.Register(
            "IsDigitOnly",
            typeof(Boolean),
            typeof(XTextBox),
            new PropertyMetadata(false));

        public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register(
            "MaxValue",
            typeof(Single),
            typeof(XTextBox),
            new PropertyMetadata(Single.NaN));

        public static readonly DependencyProperty IsPasswordProperty = DependencyProperty.Register(
            "IsPassword",
            typeof(Boolean),
            typeof(XTextBox),
            new PropertyMetadata(false));

        public static readonly DependencyProperty VisibilityMainTextProperty = DependencyProperty.Register(
            "VisibilityMainText",
            typeof(Visibility),
            typeof(XTextBox),
            new PropertyMetadata(Visibility.Visible));

        #endregion //DependencyProperties

        #region Properties 
        [Description("Gets or sets the watermark title")]
        public String Watermark
        {
            get { return (String)GetValue(WatermarkProperty); }
            set { SetValue(WatermarkProperty, value); }
        }

        [Description("Gets or sets the watermark vertical alignment")]
        public VerticalAlignment WatermarkVerticalAlignment
        {
            get { return (VerticalAlignment)GetValue(WatermarkVerticalAlignmentProperty); }
            set { SetValue(WatermarkVerticalAlignmentProperty, value); }
        }


        [Description("Gets or sets the watermark title color")]
        public Brush WatermarkForeground
        {
            get { return (Brush)GetValue(WatermarkVerticalAlignmentProperty); }
            set { SetValue(WatermarkVerticalAlignmentProperty, value); }
        }

        [Description("Gets or sets the watermark title font size")]
        public Double WatermarkFontSize
        {
            get { return (Double)GetValue(WatermarkVerticalAlignmentProperty); }
            set { SetValue(WatermarkVerticalAlignmentProperty, value); }
        }

        [Description("Gets or sets the textbox floating mode")]
        public Boolean IsFloating
        {
            get { return (Boolean)GetValue(IsFloatingProperty); }
            set { SetValue(IsFloatingProperty, value); }
        }

        [Description("Gets or sets the textbox access of negative values")]
        public Boolean IsAccessNegative
        {
            get { return (Boolean)GetValue(IsAccessNegativeProperty); }
            set { SetValue(IsAccessNegativeProperty, value); }
        }

        [Description("Gets or sets the textbox chars type")]
        public Boolean IsDigitOnly
        {
            get { return (Boolean)GetValue(IsDigitOnlyProperty); }
            set { SetValue(IsDigitOnlyProperty, value); }
        }

        [Description("Gets or sets the max input value (enable in digit mode only)")]
        public Single MaxValue
        {
            get { return (Single)GetValue(MaxValueProperty); }
            set { SetValue(MaxValueProperty, value); }
        }

        [Description("Gets or sets the textbox is passwordbox")]
        public Boolean IsPassword
        {
            get { return (Boolean)GetValue(IsPasswordProperty); }
            set { SetValue(IsPasswordProperty, value); }
        }

        public Visibility VisibilityMainText
        {
            get { return (Visibility)GetValue(VisibilityMainTextProperty); }
            set { SetValue(VisibilityMainTextProperty, value); }
        }

        #endregion //Properties

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            PART_Watermark = GetTemplateChild("PART_Watermark") as TextBlock;
            PART_Pasword = GetTemplateChild("PART_Pasword") as TextBlock;
            SetWatermarkVisibility();
            if (IsPassword)
            {
                VisibilityMainText = Visibility.Collapsed;
                if (PART_Pasword != null)
                {
                    PART_Pasword.Visibility = Visibility.Visible;
                    PART_Pasword.FontSize = 20;
                }
            }
            else
            {
                VisibilityMainText = Visibility.Visible;
            }

            DataObject.AddPastingHandler(this, OnPaste);
        }

        protected void OnPaste(Object sender, DataObjectPastingEventArgs e)
        {
            try
            {
                var isText = e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true);
                if (!isText) return;
                var text = e.SourceDataObject.GetData(DataFormats.UnicodeText) as String;
                if (!String.IsNullOrEmpty(text))
                {
                    if (IsDigitOnly)
                    {
                        if (!IsAccessNegative)
                        {
                            var ch = text[0];
                            if (ch == 45)
                            {
                                e.CancelCommand();
                            }
                        }
                        for (int i = 0; i < text.Length; i++)
                        {
                            if (i == 0)
                            {
                                if (IsAccessNegative && text[i] == 45)
                                {
                                    continue;
                                }
                            }
                            if (!Char.IsDigit(text[0]))
                                e.CancelCommand();
                        }
                    }
                }
            }
            catch (Exception)
            {
                // ignored
                e.Handled = true;
            }
        }

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);
            SetWatermarkVisibility();
            if (IsPassword)
            {
                PART_Pasword.Text = new String('•', Text.Length);
            }
        }

        protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
        {
            base.OnLostKeyboardFocus(e);
            SetWatermarkVisibility();
        }

        protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
        {
            base.OnGotKeyboardFocus(e);
            if (PART_Watermark != null)
            {
                PART_Watermark.Visibility = Visibility.Hidden;
            }
        }

        protected override void OnPreviewTextInput(TextCompositionEventArgs e)
        {
            base.OnPreviewTextInput(e);
            if (e.Text.Length == 0)
            {
                e.Handled = true;
                return;
            }
            if (IsDigitOnly)
            {
                var ch = e.Text[0];
                if (!Char.IsDigit(ch) && ch != 8 && ch != 46)
                {
                    if (!(IsAccessNegative && ch == 45))
                        e.Handled = true;
                }
                if (IsFloating)
                {
                    if (ch == 46 && Text.IndexOf('.') != -1)
                    {
                        e.Handled = true;
                        return;
                    }
                }

                if (!IsAccessNegative)
                {
                    if (ch == 45)
                    {
                        e.Handled = true;
                    }
                }
            }
        }

        #region Private

        private void SetWatermarkVisibility()
        {
            if (PART_Watermark != null)
            {
                PART_Watermark.Visibility = (Text != String.Empty || IsKeyboardFocused)? Visibility.Hidden : Visibility.Visible;
            }
        }
        #endregion
    }
}

Screenshot from UISpy


回答1:


Let me know if that works

TextBox = (TextBox)CreateBranch
         .Get(SearchCriteria.ByAutomationId("Title").AndOfFramework(WindowsFramework.Wpf));

Edited after new source added

You have to create a specific AutomationPeer for your custom control and return it via the override of the method OnCreateAutomationPeer().

Your control is a subclass of the TextBox control so you can just return a new TextBoxAutomationPeer instance or create your custom AutomationPeer from it.

public class XTextBox : TextBox
{
...
    protected override AutomationPeer OnCreateAutomationPeer()
    {
        return new XTextBoxAutomationPeer(this);
        // or just use the TextBoxAutomationPeer
        // return new TextBoxAutomationPeer(this);
    }
...
}

The custom automation peer

public class XTextBoxAutomationPeer : TextBoxAutomationPeer
{
    public XTextBoxAutomationPeer(XTextBox owner)
        : base(owner)
    {
    }

    protected override string GetClassNameCore()
    {
        return "XTextBox";
    }
}



回答2:


[SetUpFixture]
    public class SETUP_THAT_WILL_GET_CALL_LATER
    {
        [OneTimeSetUp]
        public void OneTimeSetUp()
        {
            var applicationDirectory = TestContext.CurrentContext.TestDirectory;
            var applicationPath = Path.Combine(applicationDirectory, @"..\..\..\, "your debug folder path here", "your application.exe here");
            Application = Application.Launch(applicationPath);

            Thread.Sleep(2000);

            Window = Application.GetWindow("Title of your application", InitializeOption.WithCache);
        }

        [OneTimeTearDown()]
        public void OneTimeTearDown()
        {
            Window.Dispose();
            Application.Dispose();
        }

        public static Application Application;
        public static Window Window;
    }

Then in your test

[Test]
public void yourtest()
{
   var textBox = SETUP_THAT_WILL_GET_CALL_LATER.**Window.Get<TextBox>("Your textbox name here");**

}


来源:https://stackoverflow.com/questions/42368114/teststack-white-doesnt-find-textbox-in-wpf-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!