| /* |
| * Copyright (C) 2020 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| |
| #if PLATFORM(IOS_FAMILY) |
| |
| #import "PlatformUtilities.h" |
| #import "TestInputDelegate.h" |
| #import "TestWKWebView.h" |
| #import "UIKitSPI.h" |
| #import "WKWebViewConfigurationExtras.h" |
| #import <WebKit/WKWebViewPrivate.h> |
| #import <wtf/unicode/CharacterNames.h> |
| |
| namespace TestWebKitAPI { |
| |
| TEST(InsertTextAlternatives, Simple) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'>A big </body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToEndOfDocument" argument:nil]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 1)"] boolValue]); // A |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(2, 3)"] boolValue]); // big |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 6)"] boolValue]); // "A big " |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(6, 5)"] boolValue]); // hello |
| } |
| |
| TEST(InsertTextAlternatives, InsertLeadingSpace) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView waitForNextPresentationUpdate]; |
| |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [[webView textInputContentView] insertText:@" "]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 1)"] boolValue]); // <space> |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(1, 5)"] boolValue]); // hello |
| } |
| |
| TEST(InsertTextAlternatives, InsertLeadingNewline) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| // Set CSS white-space and user-modify so that \n is inserted literally. Otherwise, it would be converted into a <br> if <body> |
| // only had "contenteditable='true'" because it is considered richly editable. |
| [webView synchronouslyLoadHTMLString:@"<body style='white-space: pre; -webkit-user-modify: read-write-plaintext-only'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [[webView textInputContentView] insertText:@"\n"]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 1)"] boolValue]); // \n |
| [webView _synchronouslyExecuteEditCommand:@"MoveDown" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 5)"] boolValue]); // hello |
| } |
| |
| static inline NSString *makeNSStringWithCharacter(unichar c) |
| { |
| return [NSString stringWithCharacters:&c length:1]; |
| }; |
| |
| TEST(InsertTextAlternatives, InsertLeadingNoBreakSpace_ExpectedFailure) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView waitForNextPresentationUpdate]; |
| |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [[webView textInputContentView] insertText:makeNSStringWithCharacter(noBreakSpace)]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 1)"] boolValue]); // <no-break space> |
| // FIXME: Change this to EXPECT_TRUE() once leading no-break spaces do not cause removal of alternatives. |
| // See <https://webkit.org/b/212098>. |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(1, 5)"] boolValue]); // hello |
| } |
| |
| TEST(InsertTextAlternatives, InsertTrailingSpace) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| // Set CSS white-space so that ' ' is inserted literally. Otherwise, it would be converted into a no-break space. |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true' style='white-space: pre'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [[webView textInputContentView] insertText:@" "]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 5)"] boolValue]); // hello |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(5, 1)"] boolValue]); // <space> |
| } |
| |
| TEST(InsertTextAlternatives, InsertTrailingSpaceWhitespaceRebalance) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [[webView textInputContentView] insertText:@" "]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 5)"] boolValue]); // hello |
| } |
| |
| TEST(InsertTextAlternatives, InsertTrailingNewline) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| // Set CSS white-space and user-modify so that \n is inserted literally. Otherwise, it would be converted into a <br> if <body> |
| // only had "contenteditable='true'" because it is considered richly editable. |
| [webView synchronouslyLoadHTMLString:@"<body style='white-space: pre; -webkit-user-modify: read-write-plaintext-only'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [[webView textInputContentView] insertText:@"\n"]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 5)"] boolValue]); // hello |
| [webView _synchronouslyExecuteEditCommand:@"MoveDown" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 1)"] boolValue]); // \n |
| } |
| |
| TEST(InsertTextAlternatives, InsertTrailingNoBreakSpace_ExpectedFailure) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [[webView textInputContentView] insertText:makeNSStringWithCharacter(noBreakSpace)]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| // FIXME: Change first EXPECT to EXPECT_TRUE() once trailing no-break spaces do not cause removal of alternatives. |
| // See <https://webkit.org/b/212098>. |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 5)"] boolValue]); // hello |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(5, 1)"] boolValue]); // <no-break space> |
| } |
| |
| TEST(InsertTextAlternatives, InsertSpaceInMiddle) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView waitForNextPresentationUpdate]; |
| |
| [webView stringByEvaluatingJavaScript:@"getSelection().setPosition(document.body.firstChild, 2)"]; |
| [[webView textInputContentView] insertText:@" "]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 2)"] boolValue]); // he |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(2, 1)"] boolValue]); // <space> |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(3, 3)"] boolValue]); // llo |
| } |
| |
| TEST(InsertTextAlternatives, InsertNewlineInMiddle_ExpectedFailure) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| // Set CSS white-space and user-modify so that \n is inserted literally. Otherwise, it would be converted into a <br> if <body> |
| // only had "contenteditable='true'" because it is considered richly editable. |
| [webView synchronouslyLoadHTMLString:@"<body style='white-space: pre; -webkit-user-modify: read-write-plaintext-only'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView waitForNextPresentationUpdate]; |
| |
| [webView stringByEvaluatingJavaScript:@"getSelection().setPosition(document.body.firstChild, 2)"]; |
| [[webView textInputContentView] insertText:@"\n"]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| // FIXME: These results coincidentally match UIKit, but they just feel weird: they are asymmetric to |
| // what happens when a space is inserted in the middle. Marker should be removed when marker is split. |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 2)"] boolValue]); // he |
| [webView _synchronouslyExecuteEditCommand:@"MoveDown" argument:nil]; |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 3)"] boolValue]); // llo |
| } |
| |
| TEST(InsertTextAlternatives, InsertNoBreakSpaceInMiddle) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| // Set CSS white-space and user-modify so that \n is inserted literally. Otherwise, it would be converted into a <br> if <body> |
| // only had "contenteditable='true'" because it is considered richly editable. |
| [webView synchronouslyLoadHTMLString:@"<body style='white-space: pre; -webkit-user-modify: read-write-plaintext-only'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView waitForNextPresentationUpdate]; |
| |
| [webView stringByEvaluatingJavaScript:@"getSelection().setPosition(document.body.firstChild, 2)"]; |
| [[webView textInputContentView] insertText:makeNSStringWithCharacter(noBreakSpace)]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 2)"] boolValue]); // he |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(2, 1)"] boolValue]); // <no-break space> |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(3, 3)"] boolValue]); // llo |
| } |
| |
| TEST(InsertTextAlternatives, InsertLeadingNonWhitespaceCharacter) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView waitForNextPresentationUpdate]; |
| |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [[webView textInputContentView] insertText:@"a"]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 1)"] boolValue]); // a |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(1, 5)"] boolValue]); // hello |
| } |
| |
| TEST(InsertTextAlternatives, InsertTrailingNonWhitespaceCharacter) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [[webView textInputContentView] insertText:@"a"]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 5)"] boolValue]); // hello |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(5, 1)"] boolValue]); // a |
| } |
| |
| TEST(InsertTextAlternatives, InsertNonWhitespaceCharacterInMiddle) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [webView waitForNextPresentationUpdate]; |
| |
| [webView stringByEvaluatingJavaScript:@"getSelection().setPosition(document.body.firstChild, 2)"]; |
| [[webView textInputContentView] insertText:@"a"]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 2)"] boolValue]); // he |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(2, 1)"] boolValue]); // a |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(3, 3)"] boolValue]); // llo |
| } |
| |
| TEST(InsertTextAlternatives, InsertMultipleWordsWithAlternatives) |
| { |
| auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; |
| auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration]); |
| auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]); |
| [inputDelegate setFocusStartsInputSessionPolicyHandler:[] (WKWebView *, id <_WKFocusedElementInfo>) { return _WKFocusStartsInputSessionPolicyAllow; }]; |
| [webView _setInputDelegate:inputDelegate.get()]; |
| |
| // Set CSS white-space so that ' ' is inserted literally. Otherwise, it would be converted into a no-break space. |
| [webView synchronouslyLoadHTMLString:@"<body contenteditable='true' style='white-space: pre'></body>"]; |
| [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"]; |
| [[webView textInputContentView] insertText:@"hello" alternatives:@[@"yellow"] style:UITextAlternativeStyleNone]; |
| [[webView textInputContentView] insertText:@" "]; |
| [[webView textInputContentView] insertText:@"worlds" alternatives:@[@"worm"] style:UITextAlternativeStyleNone]; |
| [webView _synchronouslyExecuteEditCommand:@"MoveToBeginningOfDocument" argument:nil]; |
| [webView waitForNextPresentationUpdate]; |
| |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(0, 5)"] boolValue]); // hello |
| EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(5, 1)"] boolValue]); // <space> |
| EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"internals.hasDictationAlternativesMarker(6, 5)"] boolValue]); // worlds |
| } |
| |
| } // namespace TestWebKitAPI |
| |
| #endif // PLATFORM(IOS_FAMILY) |
| |