123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- using System;
- using System.Linq;
- using NUnit.Framework;
- using UnityEngine;
- using UnityEngine.EventSystems;
- using UnityEngine.TestTools;
- using System.Collections;
- using System.IO;
- using UnityEditor;
- using UnityEngine.UI;
- using System.Reflection;
-
- namespace InputfieldTests
- {
- public class TouchInputFieldTests : BaseInputFieldTests, IPrebuildSetup
- {
- protected const string kPrefabPath = "Assets/Resources/TouchInputFieldPrefab.prefab";
-
- public void Setup()
- {
- #if UNITY_EDITOR
- CreateInputFieldAsset(kPrefabPath);
- #endif
- }
-
- [SetUp]
- public void TestSetup()
- {
- m_PrefabRoot = UnityEngine.Object.Instantiate(Resources.Load("TouchInputFieldPrefab")) as GameObject;
-
- FieldInfo inputModule = typeof(EventSystem).GetField("m_CurrentInputModule", BindingFlags.NonPublic | BindingFlags.Instance);
- inputModule.SetValue(m_PrefabRoot.GetComponentInChildren<EventSystem>(), m_PrefabRoot.GetComponentInChildren<FakeInputModule>());
- }
-
- [TearDown]
- public void TearDown()
- {
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- TouchScreenKeyboard.hideInput = false;
- FontUpdateTracker.UntrackText(m_PrefabRoot.GetComponentInChildren<Text>());
- GameObject.DestroyImmediate(m_PrefabRoot);
- }
-
- [OneTimeTearDown]
- public void OnetimeTearDown()
- {
- #if UNITY_EDITOR
- AssetDatabase.DeleteAsset(kPrefabPath);
- #endif
- }
-
- protected const string kDefaultInputStr = "foobar";
-
- const string kEmailSpecialCharacters = "!#$%&'*+-/=?^_`{|}~";
-
- public struct CharValidationTestData
- {
- public string input, output;
- public InputField.CharacterValidation validation;
-
- public CharValidationTestData(string input, string output, InputField.CharacterValidation validation)
- {
- this.input = input;
- this.output = output;
- this.validation = validation;
- }
-
- public override string ToString()
- {
- // these won't properly show up if test runners UI if we don't replace it
- string input = this.input.Replace(kEmailSpecialCharacters, "specialchars");
- string output = this.output.Replace(kEmailSpecialCharacters, "specialchars");
- return string.Format("input={0}, output={1}, validation={2}", input, output, validation);
- }
- }
-
- [Test]
- [TestCase("*Azé09", "*Azé09", InputField.CharacterValidation.None)]
- [TestCase("*Azé09?.", "Az09", InputField.CharacterValidation.Alphanumeric)]
- [TestCase("Abc10x", "10", InputField.CharacterValidation.Integer)]
- [TestCase("-10", "-10", InputField.CharacterValidation.Integer)]
- [TestCase("10.0", "100", InputField.CharacterValidation.Integer)]
- [TestCase("10.0", "10.0", InputField.CharacterValidation.Decimal)]
- [TestCase(" -10.0x", "-10.0", InputField.CharacterValidation.Decimal)]
- [TestCase("10,0", "10,0", InputField.CharacterValidation.Decimal)]
- [TestCase(" -10,0x", "-10,0", InputField.CharacterValidation.Decimal)]
- [TestCase("A10,0 ", "10,0", InputField.CharacterValidation.Decimal)]
- [TestCase("A'a aaa aaa", "A'a Aaa Aaa", InputField.CharacterValidation.Name)]
- [TestCase("Unity-Editor", "Unity-Editor", InputField.CharacterValidation.Name)]
- [TestCase("Unity--Editor", "Unity-Editor", InputField.CharacterValidation.Name)]
- [TestCase("-UnityEditor", "Unityeditor", InputField.CharacterValidation.Name)]
- [TestCase(" _JOHN* (Doe)", "John Doe", InputField.CharacterValidation.Name)]
- [TestCase("johndoe@unity3d.com", "johndoe@unity3d.com", InputField.CharacterValidation.EmailAddress)]
- [TestCase(">john doe\\@unity3d.com", "johndoe@unity3d.com", InputField.CharacterValidation.EmailAddress)]
- [TestCase(kEmailSpecialCharacters + "@unity3d.com", kEmailSpecialCharacters + "@unity3d.com", InputField.CharacterValidation.EmailAddress)]
- public void HonorsCharacterValidationSettingsAssignment(string input, string output, InputField.CharacterValidation validation)
- {
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- inputField.characterValidation = validation;
- inputField.text = input;
- Assert.AreEqual(output, inputField.text, string.Format("Failed character validation: input ={0}, output ={1}, validation ={2}",
- input.Replace(kEmailSpecialCharacters, "specialchars"),
- output.Replace(kEmailSpecialCharacters, "specialchars"),
- validation));
- }
-
- [UnityTest]
- [TestCase("*Azé09", "*Azé09", InputField.CharacterValidation.None, ExpectedResult = null)]
- [TestCase("*Azé09?.", "Az09", InputField.CharacterValidation.Alphanumeric, ExpectedResult = null)]
- [TestCase("Abc10x", "10", InputField.CharacterValidation.Integer, ExpectedResult = null)]
- [TestCase("-10", "-10", InputField.CharacterValidation.Integer, ExpectedResult = null)]
- [TestCase("10.0", "100", InputField.CharacterValidation.Integer, ExpectedResult = null)]
- [TestCase("10.0", "10.0", InputField.CharacterValidation.Decimal, ExpectedResult = null)]
- [TestCase(" -10.0x", "-10.0", InputField.CharacterValidation.Decimal, ExpectedResult = null)]
- [TestCase("10,0", "10,0", InputField.CharacterValidation.Decimal, ExpectedResult = null)]
- [TestCase(" -10,0x", "-10,0", InputField.CharacterValidation.Decimal, ExpectedResult = null)]
- [TestCase("A10,0 ", "10,0", InputField.CharacterValidation.Decimal, ExpectedResult = null)]
- [TestCase("A'a aaa aaa", "A'a Aaa Aaa", InputField.CharacterValidation.Name, ExpectedResult = null)]
- [TestCase(" _JOHN* (Doe)", "John Doe", InputField.CharacterValidation.Name, ExpectedResult = null)]
- [TestCase("johndoe@unity3d.com", "johndoe@unity3d.com", InputField.CharacterValidation.EmailAddress, ExpectedResult = null)]
- [TestCase(">john doe\\@unity3d.com", "johndoe@unity3d.com", InputField.CharacterValidation.EmailAddress, ExpectedResult = null)]
- [TestCase(kEmailSpecialCharacters + "@unity3d.com", kEmailSpecialCharacters + "@unity3d.com", InputField.CharacterValidation.EmailAddress, ExpectedResult = null)]
- public IEnumerator HonorsCharacterValidationSettingsTypingWithSelection(string input, string output, InputField.CharacterValidation validation)
- {
- if (!TouchScreenKeyboard.isSupported)
- yield break;
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- BaseEventData eventData = new BaseEventData(m_PrefabRoot.GetComponentInChildren<EventSystem>());
- inputField.characterValidation = validation;
- inputField.text = input;
-
- #if UNITY_GAMECORE && !UNITY_EDITOR
- // Address instabilities: UUM-34900, UUM-32902
- // Cause:
- // On Xbox devkits, the PLM (Process Lifetime Management) suspends the application when the on-screen keyboard is opened.
- // This cause subsequent tests to fail because the event system will ignore input when the application is not focused.
- // Resolution:
- // Yielding any call that trigger OSK (open and closure) to ensure the OSK is in the expected stated before continuing the test.
- // Note:
- // UNITY_GAMECORE affects all GDK compatible platforms (Xbox One, Series and Windows).
- // As PLM is only a GDK for consoles feature, this fix have to be enforced on console platforms only.
-
- do
- {
- inputField.OnSelect(eventData);
- yield return null;
- }
- while (!TouchScreenKeyboard.visible);
- #else
- inputField.OnSelect(eventData);
- yield return null;
- #endif
-
- Assert.AreEqual(output, inputField.text, string.Format("Failed character validation: input ={0}, output ={1}, validation ={2}",
- input.Replace(kEmailSpecialCharacters, "specialchars"),
- output.Replace(kEmailSpecialCharacters, "specialchars"),
- validation));
-
- #if UNITY_GAMECORE && !UNITY_EDITOR
- do
- {
- // We manually close the OSK as we don't need to assert the inputField afterward.
- if (inputField.touchScreenKeyboard != null)
- {
- inputField.touchScreenKeyboard.active = false;
- }
-
- // No delay is needed here as we don't use inputField.OnDeselect.
- yield return null;
- }
- while (TouchScreenKeyboard.visible);
- #endif
- }
-
- [Test]
- public void AssignmentAgainstCharacterLimit([Values("ABC", "abcdefghijkl")] string text)
- {
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- // test assignment
- inputField.characterLimit = 5;
- inputField.text = text;
- Assert.AreEqual(text.Substring(0, Math.Min(text.Length, inputField.characterLimit)), inputField.text);
- }
-
- [Test] // regression test 793119
- public void AssignmentAgainstCharacterLimitWithContentType([Values("Abc", "Abcdefghijkl")] string text)
- {
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- // test assignment
- inputField.characterLimit = 5;
- inputField.contentType = InputField.ContentType.Name;
- inputField.text = text;
- Assert.AreEqual(text.Substring(0, Math.Min(text.Length, inputField.characterLimit)), inputField.text);
- }
-
- [UnityTest]
- [UnityPlatform(exclude = new[] { RuntimePlatform.tvOS })] // UUM-71764 (tvOS)
- public IEnumerator SendsEndEditEventOnDeselect()
- {
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- BaseEventData eventData = new BaseEventData(m_PrefabRoot.GetComponentInChildren<EventSystem>());
-
- #if UNITY_GAMECORE && !UNITY_EDITOR
- do
- {
- inputField.OnSelect(eventData);
-
- // If 2 tests trying to open and close the OSK are called in a row, the seconds test would always hang for 2 to 3 minutes.
- // This seemed to happens everytime the OSK is disabled using input.OnDeselect before being re-enabled using input.OnSelect.
- // Adding these 0.2s delay on in these case allows to get rid of the hang.
- yield return new WaitForSecondsRealtime(0.2f);
- }
- while (!TouchScreenKeyboard.visible);
- #else
- inputField.OnSelect(eventData);
- yield return null;
- #endif
- var called = false;
- inputField.onEndEdit.AddListener((s) => { called = true; });
-
- #if UNITY_GAMECORE && !UNITY_EDITOR
- do
- {
- inputField.OnDeselect(eventData);
- yield return new WaitForSecondsRealtime(0.2f);
- }
- while (TouchScreenKeyboard.visible);
- #else
- inputField.OnDeselect(eventData);
- #endif
-
- Assert.IsTrue(called, "Expected invocation of onEndEdit");
- }
-
- [Test]
- public void StripsNullCharacters2()
- {
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- inputField.text = "a\0b";
- Assert.AreEqual("ab", inputField.text, "\\0 characters should be stripped");
- }
-
- [UnityTest]
- [UnityPlatform(exclude = new[] { RuntimePlatform.tvOS })] // UUM-71764 (tvOS)
- public IEnumerator FocusOpensTouchScreenKeyboard()
- {
- var isInPlaceEditingDisabled = typeof(TouchScreenKeyboard).GetProperty("disableInPlaceEditing",
- System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- isInPlaceEditingDisabled.SetValue(null, true);
-
- if (!TouchScreenKeyboard.isSupported)
- yield break;
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- BaseEventData eventData = new BaseEventData(m_PrefabRoot.GetComponentInChildren<EventSystem>());
-
- #if UNITY_GAMECORE && !UNITY_EDITOR
- do
- {
- inputField.OnSelect(eventData);
- yield return new WaitForSecondsRealtime(0.2f);
- }
- while (!TouchScreenKeyboard.visible);
- #else
- inputField.OnSelect(eventData);
- yield return null;
- #endif
-
- Assert.NotNull(inputField.touchScreenKeyboard, "Expect a keyboard to be opened");
-
- #if UNITY_GAMECORE && !UNITY_EDITOR
- do
- {
- inputField.OnDeselect(eventData);
- yield return new WaitForSecondsRealtime(0.2f);
- }
- while (TouchScreenKeyboard.visible);
- #endif
- }
-
- [UnityTest]
- public IEnumerator AssignsShouldHideInput()
- {
- if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
- {
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- BaseEventData eventData = new BaseEventData(m_PrefabRoot.GetComponentInChildren<EventSystem>());
-
- inputField.shouldHideMobileInput = false;
-
- inputField.OnSelect(eventData);
- yield return null;
-
- Assert.IsFalse(inputField.shouldHideMobileInput);
- Assert.IsFalse(TouchScreenKeyboard.hideInput, "Expect TouchScreenKeyboard.hideInput to be set");
- }
- }
-
- [UnityTest, Ignore("Disabled for Instability https://jira.unity3d.com/browse/UUM-69542")]
- [UnityPlatform(exclude = new[] { RuntimePlatform.IPhonePlayer, RuntimePlatform.PS4, RuntimePlatform.PS5, RuntimePlatform.VisionOS })] // disabled on visionOS due to UUM-61018
- public IEnumerator IsTouchScreenKeyboardVisible()
- {
- const float ActionTimeout = 3.0f;
- if (!TouchScreenKeyboard.isSupported)
- yield break;
-
- InputField inputField = m_PrefabRoot.GetComponentInChildren<InputField>();
- BaseEventData eventData = new BaseEventData(m_PrefabRoot.GetComponentInChildren<EventSystem>());
-
- inputField.OnSelect(eventData);
- yield return WaitForCondition("Waiting for keyboard to show", () => TouchScreenKeyboard.visible, ActionTimeout);
-
- inputField.OnDeselect(eventData);
- yield return WaitForCondition("Waiting for keyboard to close", () => !TouchScreenKeyboard.visible, ActionTimeout);
- }
- }
- }
|