// // Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The SFC licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // using NUnit.Framework; using OpenQA.Selenium.Environment; using System; using System.Runtime.InteropServices; namespace OpenQA.Selenium; [TestFixture] public class TypingTest : DriverTestFixture { [Test] public void ShouldFireKeyPressEvents() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("a"); IWebElement result = driver.FindElement(By.Id("result")); string text = result.Text; Assert.That(text, Does.Contain("press:")); } [Test] public void ShouldFireKeyDownEvents() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("I"); IWebElement result = driver.FindElement(By.Id("result")); string text = result.Text; Assert.That(text, Does.Contain("down:")); } [Test] public void ShouldFireKeyUpEvents() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("a"); IWebElement result = driver.FindElement(By.Id("result")); string text = result.Text; Assert.That(text, Does.Contain("up:")); } [Test] public void ShouldTypeLowerCaseLetters() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("abc def"); Assert.That(keyReporter.GetAttribute("value"), Is.EqualTo("abc def")); } [Test] public void ShouldBeAbleToTypeCapitalLetters() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("ABC DEF"); Assert.That(keyReporter.GetAttribute("value"), Is.EqualTo("ABC DEF")); } [Test] public void ShouldBeAbleToTypeQuoteMarks() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("\""); Assert.That(keyReporter.GetAttribute("value"), Is.EqualTo("\"")); } [Test] public void ShouldBeAbleToTypeTheAtCharacter() { // simon: I tend to use a US/UK or AUS keyboard layout with English // as my primary language. There are consistent reports that we're // not handling i18nised keyboards properly. This test exposes this // in a lightweight manner when my keyboard is set to the DE mapping // and we're using IE. driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("@"); Assert.That(keyReporter.GetAttribute("value"), Is.EqualTo("@")); } [Test] public void ShouldBeAbleToMixUpperAndLowerCaseLetters() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("me@eXample.com"); Assert.That(keyReporter.GetAttribute("value"), Is.EqualTo("me@eXample.com")); } [Test] public void ArrowKeysShouldNotBePrintable() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys(Keys.ArrowLeft); Assert.That(keyReporter.GetAttribute("value"), Is.Empty); } [Test] public void ShouldBeAbleToUseArrowKeys() { driver.Url = javascriptPage; IWebElement keyReporter = driver.FindElement(By.Id("keyReporter")); keyReporter.SendKeys("Tet" + Keys.ArrowLeft + "s"); Assert.That(keyReporter.GetAttribute("value"), Is.EqualTo("Test")); } [Test] public void WillSimulateAKeyUpWhenEnteringTextIntoInputElements() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyUp")); element.SendKeys("I like cheese"); IWebElement result = driver.FindElement(By.Id("result")); Assert.That(result.Text, Is.EqualTo("I like cheese")); } [Test] public void WillSimulateAKeyDownWhenEnteringTextIntoInputElements() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyDown")); element.SendKeys("I like cheese"); IWebElement result = driver.FindElement(By.Id("result")); // Because the key down gets the result before the input element is // filled, we're a letter short here Assert.That(result.Text, Is.EqualTo("I like chees")); } [Test] public void WillSimulateAKeyPressWhenEnteringTextIntoInputElements() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyPress")); element.SendKeys("I like cheese"); IWebElement result = driver.FindElement(By.Id("result")); // Because the key down gets the result before the input element is // filled, we're a letter short here Assert.That(result.Text, Is.EqualTo("I like chees")); } [Test] public void WillSimulateAKeyUpWhenEnteringTextIntoTextAreas() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyUpArea")); element.SendKeys("I like cheese"); IWebElement result = driver.FindElement(By.Id("result")); Assert.That(result.Text, Is.EqualTo("I like cheese")); } [Test] public void WillSimulateAKeyDownWhenEnteringTextIntoTextAreas() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyDownArea")); element.SendKeys("I like cheese"); IWebElement result = driver.FindElement(By.Id("result")); // Because the key down gets the result before the input element is // filled, we're a letter short here Assert.That(result.Text, Is.EqualTo("I like chees")); } [Test] public void WillSimulateAKeyPressWhenEnteringTextIntoTextAreas() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyPressArea")); element.SendKeys("I like cheese"); IWebElement result = driver.FindElement(By.Id("result")); // Because the key down gets the result before the input element is // filled, we're a letter short here Assert.That(result.Text, Is.EqualTo("I like chees")); } [Test] public void ShouldFireFocusKeyEventsInTheRightOrder() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("theworks")); element.SendKeys("a"); Assert.That(result.Text.Trim(), Is.EqualTo("focus keydown keypress keyup")); } [Test] public void ShouldReportKeyCodeOfArrowKeys() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys(Keys.ArrowDown); CheckRecordedKeySequence(result, 40); element.SendKeys(Keys.ArrowUp); CheckRecordedKeySequence(result, 38); element.SendKeys(Keys.ArrowLeft); CheckRecordedKeySequence(result, 37); element.SendKeys(Keys.ArrowRight); CheckRecordedKeySequence(result, 39); // And leave no rubbish/printable keys in the "keyReporter" Assert.That(element.GetAttribute("value"), Is.Empty); } [Test] public void ShouldReportKeyCodeOfArrowKeysUpDownEvents() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys(Keys.ArrowDown); string text = result.Text.Trim(); Assert.That(text, Does.Contain("down: 40")); Assert.That(text, Does.Contain("up: 40")); element.SendKeys(Keys.ArrowUp); text = result.Text.Trim(); Assert.That(text, Does.Contain("down: 38")); Assert.That(text, Does.Contain("up: 38")); element.SendKeys(Keys.ArrowLeft); text = result.Text.Trim(); Assert.That(text, Does.Contain("down: 37")); Assert.That(text, Does.Contain("up: 37")); element.SendKeys(Keys.ArrowRight); text = result.Text.Trim(); Assert.That(text, Does.Contain("down: 39")); Assert.That(text, Does.Contain("up: 39")); // And leave no rubbish/printable keys in the "keyReporter" Assert.That(element.GetAttribute("value"), Is.Empty); } [Test] public void NumericNonShiftKeys() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); string numericLineCharsNonShifted = "`1234567890-=[]\\;,.'/42"; element.SendKeys(numericLineCharsNonShifted); Assert.That(element.GetAttribute("value"), Is.EqualTo(numericLineCharsNonShifted)); } [Test] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/646")] public void NumericShiftKeys() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("keyReporter")); string numericShiftsEtc = "~!@#$%^&*()_+{}:\"<>?|END~"; element.SendKeys(numericShiftsEtc); Assert.That(element.GetAttribute("value"), Is.EqualTo(numericShiftsEtc)); string text = result.Text.Trim(); Assert.That(text, Does.Contain(" up: 16")); } [Test] public void LowerCaseAlphaKeys() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); String lowerAlphas = "abcdefghijklmnopqrstuvwxyz"; element.SendKeys(lowerAlphas); Assert.That(element.GetAttribute("value"), Is.EqualTo(lowerAlphas)); } [Test] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/646")] public void UppercaseAlphaKeys() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("keyReporter")); String upperAlphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; element.SendKeys(upperAlphas); Assert.That(element.GetAttribute("value"), Is.EqualTo(upperAlphas)); string text = result.Text.Trim(); Assert.That(text, Does.Contain(" up: 16")); } [Test] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/646")] public void AllPrintableKeys() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("keyReporter")); String allPrintable = "!\"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNO" + "PQRSTUVWXYZ [\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; element.SendKeys(allPrintable); Assert.That(element.GetAttribute("value"), Is.EqualTo(allPrintable)); string text = result.Text.Trim(); Assert.That(text, Does.Contain(" up: 16")); } [Test] public void ArrowKeysAndPageUpAndDown() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("a" + Keys.Left + "b" + Keys.Right + Keys.Up + Keys.Down + Keys.PageUp + Keys.PageDown + "1"); Assert.That(element.GetAttribute("value"), Is.EqualTo("ba1")); } [Test] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/2015")] public void HomeAndEndAndPageUpAndPageDownKeys() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("abc" + HomeKey() + "0" + Keys.Left + Keys.Right + Keys.PageUp + Keys.PageDown + EndKey() + "1" + HomeKey() + "0" + Keys.PageUp + EndKey() + "111" + HomeKey() + "00"); Assert.That(element.GetAttribute("value"), Is.EqualTo("0000abc1111")); } [Test] public void DeleteAndBackspaceKeys() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("abcdefghi"); Assert.That(element.GetAttribute("value"), Is.EqualTo("abcdefghi")); element.SendKeys(Keys.Left + Keys.Left + Keys.Delete); Assert.That(element.GetAttribute("value"), Is.EqualTo("abcdefgi")); element.SendKeys(Keys.Left + Keys.Left + Keys.Backspace); Assert.That(element.GetAttribute("value"), Is.EqualTo("abcdfgi")); } [Test] public void SpecialSpaceKeys() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("abcd" + Keys.Space + "fgh" + Keys.Space + "ij"); Assert.That(element.GetAttribute("value"), Is.EqualTo("abcd fgh ij")); } [Test] public void NumberpadKeys() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("abcd" + Keys.Multiply + Keys.Subtract + Keys.Add + Keys.Decimal + Keys.Separator + Keys.NumberPad0 + Keys.NumberPad9 + Keys.Add + Keys.Semicolon + Keys.Equal + Keys.Divide + Keys.NumberPad3 + "abcd"); Assert.That(element.GetAttribute("value"), Is.EqualTo("abcd*-+.,09+;=/3abcd")); } [Test] public void FunctionKeys() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("FUNCTION" + Keys.F8 + "-KEYS" + Keys.F8); element.SendKeys("" + Keys.F8 + "-TOO" + Keys.F8); Assert.That(element.GetAttribute("value"), Is.EqualTo("FUNCTION-KEYS-TOO")); } [Test] public void ShiftSelectionDeletes() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("abcd efgh"); Assert.That(element.GetAttribute("value"), Is.EqualTo("abcd efgh")); //Could be chord problem element.SendKeys(Keys.Shift + Keys.Left + Keys.Left + Keys.Left); element.SendKeys(Keys.Delete); Assert.That(element.GetAttribute("value"), Is.EqualTo("abcd e")); } [Test] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/646")] public void ChordControlHomeShiftEndDelete() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("!\"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFG"); element.SendKeys(HomeKey()); element.SendKeys("" + Keys.Shift + EndKey() + Keys.Delete); Assert.That(element.GetAttribute("value"), Is.Empty); string text = result.Text.Trim(); Assert.That(text, Does.Contain(" up: 16")); } [Test] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/2015")] public void ChordReverseShiftHomeSelectionDeletes() { driver.Url = javascriptPage; IWebElement result = driver.FindElement(By.Id("result")); IWebElement element = driver.FindElement(By.Id("keyReporter")); element.SendKeys("done" + HomeKey()); Assert.That(element.GetAttribute("value"), Is.EqualTo("done")); //Sending chords element.SendKeys("" + Keys.Shift + "ALL " + HomeKey()); Assert.That(element.GetAttribute("value"), Is.EqualTo("ALL done")); element.SendKeys(Keys.Delete); Assert.That(element.GetAttribute("value"), Is.EqualTo("done"), "done"); element.SendKeys("" + EndKey() + Keys.Shift + HomeKey()); Assert.That(element.GetAttribute("value"), Is.EqualTo("done")); // Note: trailing SHIFT up here string text = result.Text.Trim(); element.SendKeys("" + Keys.Delete); Assert.That(element.GetAttribute("value"), Is.Empty); } [Test] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/2015")] public void ChordControlCutAndPaste() { driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); String paste = "!\"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFG"; element.SendKeys(paste); Assert.That(element.GetAttribute("value"), Is.EqualTo(paste)); //Chords element.SendKeys("" + HomeKey() + Keys.Shift + EndKey()); element.SendKeys(PrimaryModifier() + "x"); Assert.That(element.GetAttribute("value"), Is.Empty); element.SendKeys(PrimaryModifier() + "v"); Assert.That(element.GetAttribute("value"), Is.EqualTo(paste)); element.SendKeys("" + Keys.Left + Keys.Left + Keys.Left + Keys.Shift + EndKey()); element.SendKeys(PrimaryModifier() + "x" + "v"); Assert.That(element.GetAttribute("value"), Is.EqualTo(paste)); element.SendKeys(HomeKey()); element.SendKeys(PrimaryModifier() + "v"); element.SendKeys(PrimaryModifier() + "v" + "v"); element.SendKeys(PrimaryModifier() + "v" + "v" + "v"); Assert.That(element.GetAttribute("value"), Is.EqualTo("EFGEFGEFGEFGEFGEFG" + paste)); element.SendKeys("" + EndKey() + Keys.Shift + HomeKey() + Keys.Null + Keys.Delete); Assert.That(element.GetAttribute("value"), Is.Empty); } [Test] public void ShouldTypeIntoInputElementsThatHaveNoTypeAttribute() { driver.Url = formsPage; IWebElement element = driver.FindElement(By.Id("no-type")); element.SendKeys("Should Say Cheese"); Assert.That(element.GetAttribute("value"), Is.EqualTo("Should Say Cheese")); } [Test] public void ShouldNotTypeIntoElementsThatPreventKeyDownEvents() { driver.Url = javascriptPage; IWebElement silent = driver.FindElement(By.Name("suppress")); silent.SendKeys("s"); Assert.That(silent.GetAttribute("value"), Is.Empty); } [Test] public void GenerateKeyPressEventEvenWhenElementPreventsDefault() { driver.Url = javascriptPage; IWebElement silent = driver.FindElement(By.Name("suppress")); IWebElement result = driver.FindElement(By.Id("result")); silent.SendKeys("s"); string text = result.Text; } [Test] public void ShouldBeAbleToTypeOnAnEmailInputField() { driver.Url = formsPage; IWebElement email = driver.FindElement(By.Id("email")); email.SendKeys("foobar"); Assert.That(email.GetAttribute("value"), Is.EqualTo("foobar")); } [Test] public void ShouldBeAbleToTypeOnANumberInputField() { driver.Url = formsPage; IWebElement numberElement = driver.FindElement(By.Id("age")); numberElement.SendKeys("33"); Assert.That(numberElement.GetAttribute("value"), Is.EqualTo("33")); } [Test] public void ShouldThrowIllegalArgumentException() { driver.Url = formsPage; IWebElement email = driver.FindElement(By.Id("age")); Assert.That(() => email.SendKeys(null), Throws.InstanceOf()); } [Test] public void CanSafelyTypeOnElementThatIsRemovedFromTheDomOnKeyPress() { driver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("key_tests/remove_on_keypress.html"); IWebElement input = driver.FindElement(By.Id("target")); IWebElement log = driver.FindElement(By.Id("log")); Assert.That(log.GetAttribute("value"), Is.EqualTo("")); input.SendKeys("b"); string expected = "keydown (target)\nkeyup (target)\nkeyup (body)"; Assert.That(GetValueText(log), Is.EqualTo(expected)); input.SendKeys("a"); // Some drivers (IE, Firefox) do not always generate the final keyup event since the element // is removed from the DOM in response to the keypress (note, this is a product of how events // are generated and does not match actual user behavior). expected += "\nkeydown (target)\na pressed; removing"; Assert.That(GetValueText(log), Is.EqualTo(expected).Or.EqualTo(expected + "\nkeyup (body)")); } [Test] public void CanClearNumberInputAfterTypingInvalidInput() { driver.Url = formsPage; IWebElement input = driver.FindElement(By.Id("age")); input.SendKeys("e"); input.Clear(); input.SendKeys("3"); Assert.That(input.GetAttribute("value"), Is.EqualTo("3")); } //------------------------------------------------------------------ // Tests below here are not included in the Java test suite //------------------------------------------------------------------ [Test] [IgnoreBrowser(Browser.Firefox, "Browser does not automatically focus body element in frame")] public void TypingIntoAnIFrameWithContentEditableOrDesignModeSet() { driver.Url = richTextPage; driver.SwitchTo().Frame("editFrame"); IWebElement element = driver.SwitchTo().ActiveElement(); element.SendKeys("Fishy"); driver.SwitchTo().DefaultContent(); IWebElement trusted = driver.FindElement(By.Id("istrusted")); IWebElement id = driver.FindElement(By.Id("tagId")); Assert.That(trusted.Text, Is.EqualTo("[true]").Or.EqualTo("[n/a]").Or.EqualTo("[]")); Assert.That(id.Text, Is.EqualTo("[frameHtml]").Or.EqualTo("[theBody]")); } [Test] [IgnoreBrowser(Browser.Firefox, "Browser does not automatically focus body element in frame")] public void NonPrintableCharactersShouldWorkWithContentEditableOrDesignModeSet() { driver.Url = richTextPage; driver.SwitchTo().Frame("editFrame"); IWebElement element = driver.SwitchTo().ActiveElement(); //Chords element.SendKeys("Dishy" + Keys.Backspace + Keys.Left + Keys.Left); element.SendKeys(Keys.Left + Keys.Left + "F" + Keys.Delete + EndKey() + "ee!"); Assert.That(element.Text, Is.EqualTo("Fishee!")); } [Test] public void ShouldBeAbleToTypeIntoEmptyContentEditableElement() { driver.Url = readOnlyPage; IWebElement editable = driver.FindElement(By.Id("content-editable")); editable.Clear(); editable.SendKeys("cheese"); // requires focus on OS X Assert.That(editable.Text, Is.EqualTo("cheese")); } [Test] // [IgnoreBrowser(Browser.Chrome, "Driver prepends text in contentEditable")] // [IgnoreBrowser(Browser.Edge, "Driver prepends text in contentEditable")] [IgnoreBrowser(Browser.Firefox, "https://github.com/mozilla/geckodriver/issues/2015")] public void ShouldBeAbleToTypeIntoContentEditableElementWithExistingValue() { driver.Url = readOnlyPage; IWebElement editable = driver.FindElement(By.Id("content-editable")); string initialText = editable.Text; editable.SendKeys(", edited"); Assert.That(editable.Text, Is.EqualTo(initialText + ", edited")); } [Test] [NeedsFreshDriver(IsCreatedAfterTest = true)] public void ShouldBeAbleToTypeIntoTinyMCE() { driver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("tinymce.html"); driver.SwitchTo().Frame("mce_0_ifr"); IWebElement editable = driver.FindElement(By.Id("tinymce")); editable.Clear(); editable.SendKeys("cheese"); // requires focus on OS X Assert.That(editable.Text, Is.EqualTo("cheese")); } private string GetValueText(IWebElement el) { // Standardize on \n and strip any trailing whitespace. return el.GetAttribute("value").Replace("\r\n", "\n").Trim(); } private void CheckRecordedKeySequence(IWebElement element, int expectedKeyCode) { string withKeyPress = string.Format("down: {0} press: {0} up: {0}", expectedKeyCode); string withoutKeyPress = string.Format("down: {0} up: {0}", expectedKeyCode); Assert.That(element.Text.Trim(), Is.AnyOf(withKeyPress, withoutKeyPress)); } private string PrimaryModifier() { return (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) ? Keys.Command : Keys.Control; } private string HomeKey() { return (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) ? Keys.Up : Keys.Home; } private string EndKey() { return (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) ? Keys.Down : Keys.End; } }