/*
 * Copyright (C) 2018 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 "IPadUserInterfaceSwizzler.h"
#import "InstanceMethodSwizzler.h"
#import "PlatformUtilities.h"
#import "TestInputDelegate.h"
#import "TestWKWebView.h"
#import "UIKitSPI.h"
#import <WebKit/WKWebViewPrivate.h>
#import <WebKitLegacy/WebEvent.h>
#import <cmath>

@interface InputAssistantItemTestingWebView : TestWKWebView
+ (UIBarButtonItemGroup *)leadingItemsForWebView:(WKWebView *)webView;
+ (UIBarButtonItemGroup *)trailingItemsForWebView:(WKWebView *)webView;
@end

@implementation InputAssistantItemTestingWebView {
    RetainPtr<UIBarButtonItemGroup> _leadingItems;
    RetainPtr<UIBarButtonItemGroup> _trailingItems;
}

- (void)fakeLeadingBarButtonItemAction
{
}

- (void)fakeTrailingBarButtonItemAction
{
}

+ (UIImage *)barButtonIcon
{
    return [UIImage imageNamed:@"TestWebKitAPI.resources/icon.png"];
}

+ (UIBarButtonItemGroup *)leadingItemsForWebView:(WKWebView *)webView
{
    static dispatch_once_t onceToken;
    static UIBarButtonItemGroup *sharedItems;
    dispatch_once(&onceToken, ^{
        auto leadingItem = adoptNS([[UIBarButtonItem alloc] initWithImage:self.barButtonIcon style:UIBarButtonItemStylePlain target:webView action:@selector(fakeLeadingBarButtonItemAction)]);
        sharedItems = [[UIBarButtonItemGroup alloc] initWithBarButtonItems:@[ leadingItem.get() ] representativeItem:nil];
    });
    return sharedItems;
}

+ (UIBarButtonItemGroup *)trailingItemsForWebView:(WKWebView *)webView
{
    static dispatch_once_t onceToken;
    static UIBarButtonItemGroup *sharedItems;
    dispatch_once(&onceToken, ^{
        auto trailingItem = adoptNS([[UIBarButtonItem alloc] initWithImage:self.barButtonIcon style:UIBarButtonItemStylePlain target:webView action:@selector(fakeTrailingBarButtonItemAction)]);
        sharedItems = [[UIBarButtonItemGroup alloc] initWithBarButtonItems:@[ trailingItem.get() ] representativeItem:nil];
    });
    return sharedItems;
}

- (UITextInputAssistantItem *)inputAssistantItem
{
    auto assistantItem = adoptNS([[UITextInputAssistantItem alloc] init]);
    [assistantItem setLeadingBarButtonGroups:@[[InputAssistantItemTestingWebView leadingItemsForWebView:self]]];
    [assistantItem setTrailingBarButtonGroups:@[[InputAssistantItemTestingWebView trailingItemsForWebView:self]]];
    return assistantItem.autorelease();
}

@end

@implementation TestWKWebView (KeyboardInputTests)

static CGRect rounded(CGRect rect)
{
    return CGRectMake(std::round(rect.origin.x), std::round(rect.origin.y), std::round(rect.size.width), std::round(rect.size.height));
}

- (void)waitForCaretViewFrameToBecome:(CGRect)frame
{
    BOOL hasEmittedWarning = NO;
    NSTimeInterval secondsToWaitUntilWarning = 2;
    NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
    while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) {
        CGRect currentFrame = rounded(self.caretViewRectInContentCoordinates);
        if (CGRectEqualToRect(currentFrame, frame))
            break;

        if (hasEmittedWarning || startTime + secondsToWaitUntilWarning >= [NSDate timeIntervalSinceReferenceDate])
            continue;

        NSLog(@"Expected a caret rect of %@, but still observed %@", NSStringFromCGRect(frame), NSStringFromCGRect(currentFrame));
        hasEmittedWarning = YES;
    }
}

- (void)waitForSelectionViewRectsToBecome:(NSArray<NSValue *> *)selectionRects
{
    BOOL hasEmittedWarning = NO;
    NSTimeInterval secondsToWaitUntilWarning = 2;
    NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
    while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) {
        NSArray<NSValue *> *currentRects = self.selectionViewRectsInContentCoordinates;
        BOOL selectionRectsMatch = YES;
        if (currentRects.count == selectionRects.count) {
            for (NSUInteger index = 0; index < selectionRects.count; ++index)
                selectionRectsMatch |= CGRectEqualToRect(selectionRects[index].CGRectValue, rounded(currentRects[index].CGRectValue));
        } else
            selectionRectsMatch = NO;

        if (selectionRectsMatch)
            break;

        if (hasEmittedWarning || startTime + secondsToWaitUntilWarning >= [NSDate timeIntervalSinceReferenceDate])
            continue;

        NSLog(@"Expected a selection rects of %@, but still observed %@", selectionRects, currentRects);
        hasEmittedWarning = YES;
    }
}

- (UIBarButtonItemGroup *)lastTrailingBarButtonGroup
{
    return self.firstResponder.inputAssistantItem.trailingBarButtonGroups.lastObject;
}

@end

@interface CustomInputWebView : TestWKWebView
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration inputView:(UIView *)inputView inputAccessoryView:(UIView *)inputAccessoryView;
@end

@implementation CustomInputWebView {
    RetainPtr<UIView> _customInputView;
    RetainPtr<UIView> _customInputAccessoryView;
}

- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration inputView:(UIView *)inputView inputAccessoryView:(UIView *)inputAccessoryView
{
    if (self = [super initWithFrame:frame configuration:configuration]) {
        _customInputView = inputView;
        _customInputAccessoryView = inputAccessoryView;
    }
    return self;
}

- (UIView *)inputView
{
    return _customInputView.get();
}

- (UIView *)inputAccessoryView
{
    return _customInputAccessoryView.get();
}

@end

static RetainPtr<TestWKWebView> webViewWithAutofocusedInput(const RetainPtr<TestInputDelegate>& inputDelegate)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);

    bool doneWaiting = false;
    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        doneWaiting = true;
        return _WKFocusStartsInputSessionPolicyAllow;
    }];
    [webView _setInputDelegate:inputDelegate.get()];
    [webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width, initial-scale=1'><input autofocus>"];

    TestWebKitAPI::Util::run(&doneWaiting);
    doneWaiting = false;
    return webView;
}

static RetainPtr<TestWKWebView> webViewWithAutofocusedInput()
{
    auto inputDelegate = adoptNS([TestInputDelegate new]);
    return webViewWithAutofocusedInput(inputDelegate);
}

namespace TestWebKitAPI {

TEST(KeyboardInputTests, FormNavigationAssistantBarButtonItems)
{
    IPadUserInterfaceSwizzler iPadUserInterface;

    auto inputDelegate = adoptNS([TestInputDelegate new]);
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    [webView _setInputDelegate:inputDelegate.get()];
    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];
    [webView synchronouslyLoadHTMLString:@"<body contenteditable>"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];

    EXPECT_EQ(2U, [webView lastTrailingBarButtonGroup].barButtonItems.count);
    EXPECT_FALSE([webView lastTrailingBarButtonGroup].hidden);

    if (![UIWebFormAccessory instancesRespondToSelector:@selector(setNextPreviousItemsVisible:)]) {
        // The rest of this test requires UIWebFormAccessory to be able to show or hide its next and previous items.
        return;
    }

    [webView _setEditable:YES];
    EXPECT_TRUE([webView lastTrailingBarButtonGroup].hidden);

    [webView _setEditable:NO];
    EXPECT_FALSE([webView lastTrailingBarButtonGroup].hidden);
}

TEST(KeyboardInputTests, ModifyInputAssistantItemBarButtonGroups)
{
    auto inputDelegate = adoptNS([TestInputDelegate new]);
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    [webView _setInputDelegate:inputDelegate.get()];
    [webView synchronouslyLoadHTMLString:@"<body contenteditable>"];
    UITextInputAssistantItem *item = [webView inputAssistantItem];
    UIBarButtonItemGroup *leadingItems = [InputAssistantItemTestingWebView leadingItemsForWebView:webView.get()];
    UIBarButtonItemGroup *trailingItems = [InputAssistantItemTestingWebView trailingItemsForWebView:webView.get()];
    item.leadingBarButtonGroups = @[ leadingItems ];
    item.trailingBarButtonGroups = @[ trailingItems ];

    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];

    EXPECT_EQ([webView firstResponder], [webView textInputContentView]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.leadingBarButtonGroups containsObject:leadingItems]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.trailingBarButtonGroups containsObject:trailingItems]);

    // Now blur and refocus the editable area, and check that the same leading and trailing button items are present.
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.blur()"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];

    EXPECT_EQ([webView firstResponder], [webView textInputContentView]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.leadingBarButtonGroups containsObject:leadingItems]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.trailingBarButtonGroups containsObject:trailingItems]);
}

TEST(KeyboardInputTests, OverrideInputAssistantItemBarButtonGroups)
{
    auto inputDelegate = adoptNS([TestInputDelegate new]);
    auto webView = adoptNS([[InputAssistantItemTestingWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    [webView _setInputDelegate:inputDelegate.get()];
    [webView synchronouslyLoadHTMLString:@"<body contenteditable>"];
    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];

    UIBarButtonItemGroup *leadingItems = [InputAssistantItemTestingWebView leadingItemsForWebView:webView.get()];
    UIBarButtonItemGroup *trailingItems = [InputAssistantItemTestingWebView trailingItemsForWebView:webView.get()];
    EXPECT_EQ([webView firstResponder], [webView textInputContentView]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.leadingBarButtonGroups containsObject:leadingItems]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.trailingBarButtonGroups containsObject:trailingItems]);

    // Now blur and refocus the editable area, and check that the same leading and trailing button items are present.
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.blur()"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];

    EXPECT_EQ([webView firstResponder], [webView textInputContentView]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.leadingBarButtonGroups containsObject:leadingItems]);
    EXPECT_TRUE([[webView firstResponder].inputAssistantItem.trailingBarButtonGroups containsObject:trailingItems]);
}

TEST(KeyboardInputTests, CustomInputViewAndInputAccessoryView)
{
    auto inputView = adoptNS([[UIView alloc] init]);
    auto inputAccessoryView = adoptNS([[UIView alloc] init]);
    auto inputDelegate = adoptNS([TestInputDelegate new]);
    [inputDelegate setWillStartInputSessionHandler:[inputView, inputAccessoryView] (WKWebView *, id<_WKFormInputSession> session) {
        session.customInputView = inputView.get();
        session.customInputAccessoryView = inputAccessoryView.get();
    }];

    auto webView = webViewWithAutofocusedInput(inputDelegate);
    EXPECT_EQ(inputView.get(), [webView firstResponder].inputView);
    EXPECT_EQ(inputAccessoryView.get(), [webView firstResponder].inputAccessoryView);
}

TEST(KeyboardInputTests, CanHandleKeyEventInCompletionHandler)
{
    auto webView = webViewWithAutofocusedInput();
    bool doneWaiting = false;

    id <UITextInputPrivate> contentView = (id <UITextInputPrivate>)[webView firstResponder];
    auto firstWebEvent = adoptNS([[WebEvent alloc] initWithKeyEventType:WebEventKeyDown timeStamp:CFAbsoluteTimeGetCurrent() characters:@"a" charactersIgnoringModifiers:@"a" modifiers:0 isRepeating:NO withFlags:0 withInputManagerHint:nil keyCode:0 isTabKey:NO]);
    auto secondWebEvent = adoptNS([[WebEvent alloc] initWithKeyEventType:WebEventKeyUp timeStamp:CFAbsoluteTimeGetCurrent() characters:@"a" charactersIgnoringModifiers:@"a" modifiers:0 isRepeating:NO withFlags:0 withInputManagerHint:nil keyCode:0 isTabKey:NO]);
    [contentView handleKeyWebEvent:firstWebEvent.get() withCompletionHandler:[&] (WebEvent *event, BOOL) {
        EXPECT_TRUE([event isEqual:firstWebEvent.get()]);
        [contentView handleKeyWebEvent:secondWebEvent.get() withCompletionHandler:[&] (WebEvent *event, BOOL) {
            EXPECT_TRUE([event isEqual:secondWebEvent.get()]);
            [contentView insertText:@"a"];
            doneWaiting = true;
        }];
    }];

    TestWebKitAPI::Util::run(&doneWaiting);
    EXPECT_WK_STREQ("a", [webView stringByEvaluatingJavaScript:@"document.querySelector('input').value"]);
}

TEST(KeyboardInputTests, ResigningFirstResponderCancelsKeyEvents)
{
    auto webView = webViewWithAutofocusedInput();
    auto contentView = [webView textInputContentView];
    auto keyDownEvent = adoptNS([[WebEvent alloc] initWithKeyEventType:WebEventKeyDown timeStamp:CFAbsoluteTimeGetCurrent() characters:@"a" charactersIgnoringModifiers:@"a" modifiers:0 isRepeating:NO withFlags:0 withInputManagerHint:nil keyCode:0 isTabKey:NO]);

    [webView becomeFirstResponder];
    [webView evaluateJavaScript:@"while(1);" completionHandler:nil];

    bool doneWaiting = false;
    [contentView handleKeyWebEvent:keyDownEvent.get() withCompletionHandler:[&] (WebEvent *event, BOOL handled) {
        EXPECT_TRUE([event isEqual:keyDownEvent.get()]);
        EXPECT_TRUE(handled);
        doneWaiting = true;
    }];

    EXPECT_TRUE([webView resignFirstResponder]);
    TestWebKitAPI::Util::run(&doneWaiting);
}

TEST(KeyboardInputTests, WaitForKeyEventHandlerInFirstResponder)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    auto contentView = [webView textInputContentView];
    auto keyDownEvent = adoptNS([[WebEvent alloc] initWithKeyEventType:WebEventKeyDown timeStamp:CFAbsoluteTimeGetCurrent() characters:@"a" charactersIgnoringModifiers:@"a" modifiers:0 isRepeating:NO withFlags:0 withInputManagerHint:nil keyCode:0 isTabKey:NO]);

    [webView becomeFirstResponder];
    [webView synchronouslyLoadHTMLString:@"<body></body>"];
    [webView evaluateJavaScript:@"start = Date.now(); while(Date.now() - start < 500);" completionHandler:nil];

    bool doneWaiting = false;
    [contentView handleKeyWebEvent:keyDownEvent.get() withCompletionHandler:[&] (WebEvent *event, BOOL handled) {
        EXPECT_TRUE([event isEqual:keyDownEvent.get()]);
        EXPECT_FALSE(handled);
        doneWaiting = true;
    }];

    TestWebKitAPI::Util::run(&doneWaiting);
}

TEST(KeyboardInputTests, CaretSelectionRectAfterRestoringFirstResponderWithRetainActiveFocusedState)
{
    // This difference in caret width is due to the fact that we don't zoom in to the input field on iPad, but do on iPhone.
    auto expectedCaretRect = CGRectMake(16, 13, UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad ? 3 : 2, 15);
    auto webView = webViewWithAutofocusedInput();
    EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]);
    [webView waitForCaretViewFrameToBecome:expectedCaretRect];

    dispatch_block_t restoreActiveFocusState = [webView _retainActiveFocusedState];
    [webView resignFirstResponder];
    restoreActiveFocusState();
    [webView waitForCaretViewFrameToBecome:CGRectZero];

    [webView becomeFirstResponder];
    [webView waitForCaretViewFrameToBecome:expectedCaretRect];
}

TEST(KeyboardInputTests, RangedSelectionRectAfterRestoringFirstResponderWithRetainActiveFocusedState)
{
    NSArray *expectedSelectionRects = @[ [NSValue valueWithCGRect:CGRectMake(16, 13, 24, 15)] ];

    auto webView = webViewWithAutofocusedInput();
    [[webView textInputContentView] insertText:@"hello"];
    [webView selectAll:nil];
    EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]);
    [webView waitForSelectionViewRectsToBecome:expectedSelectionRects];

    dispatch_block_t restoreActiveFocusState = [webView _retainActiveFocusedState];
    [webView resignFirstResponder];
    restoreActiveFocusState();
    [webView waitForSelectionViewRectsToBecome:@[ ]];

    [webView becomeFirstResponder];
    [webView waitForSelectionViewRectsToBecome:expectedSelectionRects];
}

TEST(KeyboardInputTests, CaretSelectionRectAfterRestoringFirstResponder)
{
    // This difference in caret width is due to the fact that we don't zoom in to the input field on iPad, but do on iPhone.
    auto expectedCaretRect = CGRectMake(16, 13, UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad ? 3 : 2, 15);
    auto webView = webViewWithAutofocusedInput();
    EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]);
    [webView waitForCaretViewFrameToBecome:expectedCaretRect];

    [webView resignFirstResponder];
    [webView waitForCaretViewFrameToBecome:CGRectZero];

    [webView becomeFirstResponder];
    [webView waitForCaretViewFrameToBecome:expectedCaretRect];
}

TEST(KeyboardInputTests, RangedSelectionRectAfterRestoringFirstResponder)
{
    NSArray *expectedSelectionRects = @[ [NSValue valueWithCGRect:CGRectMake(16, 13, 24, 15)] ];

    auto webView = webViewWithAutofocusedInput();
    [[webView textInputContentView] insertText:@"hello"];
    [webView selectAll:nil];
    EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]);
    [webView waitForSelectionViewRectsToBecome:expectedSelectionRects];

    [webView resignFirstResponder];
    [webView waitForSelectionViewRectsToBecome:@[ ]];

    [webView becomeFirstResponder];
    [webView waitForSelectionViewRectsToBecome:expectedSelectionRects];
}

TEST(KeyboardInputTests, KeyboardTypeForInput)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]);

    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];
    [webView _setInputDelegate:inputDelegate.get()];
    [webView synchronouslyLoadHTMLString:@"<input id='input'>"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"input.focus()"];

    auto runTest = ^(NSString *inputType, NSString *inputMode, NSString *pattern, UIKeyboardType expectedKeyboardType) {
        [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"input.blur()"];
        [webView evaluateJavaScriptAndWaitForInputSessionToChange:[NSString stringWithFormat:@"input.type = '%@'; input.inputMode = '%@'; input.pattern = '%@'; input.focus()", inputType, inputMode, pattern]];

        UIView<UITextInputPrivate> *textInput = (UIView<UITextInputPrivate> *)[webView textInputContentView];
        UIKeyboardType keyboardType = [textInput textInputTraits].keyboardType;

        bool success = keyboardType == expectedKeyboardType;
        if (!success)
            NSLog(@"Displayed %li for <input type='%@' inputmode='%@' pattern='%@'>. Expected %li.", (long)keyboardType, inputType, inputMode, pattern, (long)expectedKeyboardType);

        return success;
    };

    NSDictionary *expectedKeyboardTypeForInputType = @{
        @"text": @(UIKeyboardTypeDefault),
        @"password": @(UIKeyboardTypeDefault),
        @"search": @(UIKeyboardTypeDefault),
        @"email": @(UIKeyboardTypeEmailAddress),
        @"tel": @(UIKeyboardTypePhonePad),
        @"number": @(UIKeyboardTypeNumbersAndPunctuation),
        @"url": @(UIKeyboardTypeURL)
    };

    NSDictionary *expectedKeyboardTypeForInputMode = @{
        @"": @(-1),
        @"text": @(UIKeyboardTypeDefault),
        @"tel": @(UIKeyboardTypePhonePad),
        @"url": @(UIKeyboardTypeURL),
        @"email": @(UIKeyboardTypeEmailAddress),
        @"numeric": @(UIKeyboardTypeNumberPad),
        @"decimal": @(UIKeyboardTypeDecimalPad),
        @"search": @(UIKeyboardTypeWebSearch)
    };

    NSDictionary *expectedKeyboardTypeForPattern = @{
        @"": @(-1),
        @"\\\\d*": @(UIKeyboardTypeNumberPad),
        @"[0-9]*": @(UIKeyboardTypeNumberPad)
    };

    for (NSString *inputType in expectedKeyboardTypeForInputType) {
        BOOL isNumberOrTextInput = [inputType isEqual:@"text"] || [inputType isEqual:@"number"];
        for (NSString *inputMode in expectedKeyboardTypeForInputMode) {
            for (NSString *pattern in expectedKeyboardTypeForPattern) {
                NSNumber *keyboardType;
                if (inputMode.length) {
                    // inputmode has the highest priority.
                    keyboardType = expectedKeyboardTypeForInputMode[inputMode];
                } else {
                    // Special case for text and number inputs that have a numeric pattern. Otherwise, the input type determines the keyboard type.
                    keyboardType = pattern.length && isNumberOrTextInput ? expectedKeyboardTypeForPattern[pattern] : expectedKeyboardTypeForInputType[inputType];
                }

                EXPECT_TRUE(runTest(inputType, inputMode, pattern, (UIKeyboardType)keyboardType.intValue));
            }
        }
    }
}

TEST(KeyboardInputTests, OverrideInputViewAndInputAccessoryView)
{
    auto inputView = adoptNS([[UIView alloc] init]);
    auto inputAccessoryView = adoptNS([[UIView alloc] init]);
    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto webView = adoptNS([[CustomInputWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 568) configuration:configuration.get() inputView:inputView.get() inputAccessoryView:inputAccessoryView.get()]);
    auto contentView = [webView textInputContentView];

    EXPECT_EQ(inputAccessoryView.get(), [contentView inputAccessoryView]);
    EXPECT_EQ(inputView.get(), [contentView inputView]);
}

TEST(KeyboardInputTests, DisableSmartQuotesAndDashes)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]);
    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];
    [webView _setInputDelegate:inputDelegate.get()];

    auto checkSmartQuotesAndDashesType = [&] (UITextSmartDashesType dashesType, UITextSmartQuotesType quotesType) {
        UITextInputTraits *traits = [[webView textInputContentView] textInputTraits];
        EXPECT_EQ(dashesType, traits.smartDashesType);
        EXPECT_EQ(quotesType, traits.smartQuotesType);
    };

    [webView synchronouslyLoadHTMLString:@"<div id='foo' contenteditable spellcheck='false'></div><textarea id='bar' spellcheck='false'></textarea><input id='baz' spellcheck='false'>"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"foo.focus()"];
    checkSmartQuotesAndDashesType(UITextSmartDashesTypeNo, UITextSmartQuotesTypeNo);
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"bar.focus()"];
    checkSmartQuotesAndDashesType(UITextSmartDashesTypeNo, UITextSmartQuotesTypeNo);
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"baz.focus()"];
    checkSmartQuotesAndDashesType(UITextSmartDashesTypeNo, UITextSmartQuotesTypeNo);

    [webView synchronouslyLoadHTMLString:@"<div id='foo' contenteditable></div><textarea id='bar' spellcheck='true'></textarea><input id='baz'>"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"foo.focus()"];
    checkSmartQuotesAndDashesType(UITextSmartDashesTypeDefault, UITextSmartQuotesTypeDefault);
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"bar.focus()"];
    checkSmartQuotesAndDashesType(UITextSmartDashesTypeDefault, UITextSmartQuotesTypeDefault);
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"baz.focus()"];
    checkSmartQuotesAndDashesType(UITextSmartDashesTypeDefault, UITextSmartQuotesTypeDefault);
}

TEST(KeyboardInputTests, SelectionClipRectsWhenPresentingInputView)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]);
    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];

    CGRect selectionClipRect = CGRectNull;
    [inputDelegate setDidStartInputSessionHandler:[&] (WKWebView *, id <_WKFormInputSession>) {
        selectionClipRect = [[webView textInputContentView] _selectionClipRect];
    }];
    [webView _setInputDelegate:inputDelegate.get()];
    [webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width, initial-scale=1'><input>"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.querySelector('input').focus()"];

    EXPECT_EQ(11, selectionClipRect.origin.x);
    EXPECT_EQ(11, selectionClipRect.origin.y);
    EXPECT_EQ(134, selectionClipRect.size.width);
    EXPECT_EQ(20, selectionClipRect.size.height);
}

TEST(KeyboardInputTests, TestWebViewAdditionalContextForStrongPasswordAssistance)
{
    NSDictionary *expected = @{ @"strongPasswordAdditionalContext" : @"testUUID" };

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]);

    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];

    [inputDelegate setWebViewAdditionalContextForStrongPasswordAssistanceHandler:[&] (WKWebView *) {
        return expected;
    }];

    [inputDelegate setFocusRequiresStrongPasswordAssistanceHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) {
        return YES;
    }];

    [webView _setInputDelegate:inputDelegate.get()];

    [webView synchronouslyLoadHTMLString:@"<input type='password' id='input'>"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.getElementById('input').focus()"];

    NSDictionary *actual = [[webView textInputContentView] _autofillContext];
    EXPECT_TRUE([[actual allValues] containsObject:expected]);
}

TEST(KeyboardInputTests, SupportsImagePaste)
{
    auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]);
    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&] (WKWebView *, id <_WKFocusedElementInfo>) -> _WKFocusStartsInputSessionPolicy {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 568)]);
    auto contentView = (id <UITextInputPrivate>)[webView textInputContentView];
    [webView synchronouslyLoadHTMLString:@"<input id='input'></input><select id='select'></select><div contenteditable id='editor'></div><textarea id='textarea'></textarea>"];
    [webView _setInputDelegate:inputDelegate.get()];

    [webView stringByEvaluatingJavaScript:@"input.focus()"];
    EXPECT_TRUE(contentView.supportsImagePaste);

    [webView stringByEvaluatingJavaScript:@"document.activeElement.blur()"];
    [webView waitForNextPresentationUpdate];
    [webView stringByEvaluatingJavaScript:@"select.focus()"];
    EXPECT_FALSE(contentView.supportsImagePaste);

    [webView stringByEvaluatingJavaScript:@"editor.focus()"];
    EXPECT_TRUE(contentView.supportsImagePaste);

    [webView stringByEvaluatingJavaScript:@"document.activeElement.blur(); input.type = 'color'"];
    [webView waitForNextPresentationUpdate];
    [webView stringByEvaluatingJavaScript:@"input.focus()"];
    EXPECT_FALSE(contentView.supportsImagePaste);

    [webView stringByEvaluatingJavaScript:@"textarea.focus()"];
    EXPECT_TRUE(contentView.supportsImagePaste);
}

TEST(KeyboardInputTests, SuppressSoftwareKeyboard)
{
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
    [webView _setSuppressSoftwareKeyboard:YES];
    [[webView window] makeKeyWindow];

    auto inputDelegate = adoptNS([[TestInputDelegate alloc] init]);
    [inputDelegate setFocusStartsInputSessionPolicyHandler:[&](WKWebView *, id <_WKFocusedElementInfo>) {
        return _WKFocusStartsInputSessionPolicyAllow;
    }];

    [webView _setInputDelegate:inputDelegate.get()];
    [webView synchronouslyLoadHTMLString:@"<body contenteditable>"];
    [webView evaluateJavaScriptAndWaitForInputSessionToChange:@"document.body.focus()"];
    EXPECT_TRUE(UIKeyboardImpl.sharedInstance._shouldSuppressSoftwareKeyboard);
}

} // namespace TestWebKitAPI

#endif // PLATFORM(IOS_FAMILY)
