/* * Copyright (C) 2017 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. */ #import "config.h" #import "EditingTestHarness.h" #import "PlatformUtilities.h" #import @implementation EditingTestHarness - (instancetype)initWithWebView:(TestWKWebView *)webView { if (self = [super init]) { _webView = webView; [_webView setUIDelegate:self]; _editorStateHistory = adoptNS([[NSMutableArray alloc] init]); } return self; } - (void)dealloc { if ([_webView UIDelegate] == self) [_webView setUIDelegate:nil]; [super dealloc]; } - (TestWKWebView *)webView { return _webView.get(); } - (NSDictionary *)latestEditorState { return self.editorStateHistory.lastObject; } - (NSArray *)editorStateHistory { return _editorStateHistory.get(); } - (void)insertParagraph { [self insertParagraphAndExpectEditorStateWith:nil]; } - (void)insertText:(NSString *)text { [self insertText:text andExpectEditorStateWith:nil]; } - (void)insertHTML:(NSString *)html { [self insertHTML:html andExpectEditorStateWith:nil]; } - (void)selectAll { [self selectAllAndExpectEditorStateWith:nil]; } - (void)deleteBackwards { [self deleteBackwardAndExpectEditorStateWith:nil]; } - (void)moveBackward { [self moveBackwardAndExpectEditorStateWith:nil]; } - (void)moveForward { [self moveForwardAndExpectEditorStateWith:nil]; } - (void)insertText:(NSString *)text andExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"InsertText" argument:text expectEntries:entries]; } - (void)insertHTML:(NSString *)html andExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"InsertHTML" argument:html expectEntries:entries]; } - (void)selectAllAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"SelectAll" argument:nil expectEntries:entries]; } - (void)moveBackwardAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"MoveBackward" argument:nil expectEntries:entries]; } - (void)moveWordBackwardAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"MoveWordBackward" argument:nil expectEntries:entries]; } - (void)moveForwardAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"MoveForward" argument:nil expectEntries:entries]; } - (void)toggleBold { [self _execCommand:@"ToggleBold" argument:nil expectEntries:nil]; } - (void)toggleItalic { [self _execCommand:@"ToggleItalic" argument:nil expectEntries:nil]; } - (void)toggleUnderline { [self _execCommand:@"ToggleUnderline" argument:nil expectEntries:nil]; } - (void)setForegroundColor:(NSString *)colorAsString { [self _execCommand:@"ForeColor" argument:colorAsString expectEntries:nil]; } - (void)alignJustifiedAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"AlignJustified" argument:nil expectEntries:entries]; } - (void)alignLeftAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"AlignLeft" argument:nil expectEntries:entries]; } - (void)alignCenterAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"AlignCenter" argument:nil expectEntries:entries]; } - (void)alignRightAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"AlignRight" argument:nil expectEntries:entries]; } - (void)insertParagraphAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"InsertParagraph" argument:nil expectEntries:entries]; } - (void)deleteBackwardAndExpectEditorStateWith:(NSDictionary *)entries { [self _execCommand:@"DeleteBackward" argument:nil expectEntries:entries]; } - (void)_execCommand:(NSString *)command argument:(NSString *)argument expectEntries:(NSDictionary *)entries { __block BOOL result = false; __block bool done = false; [_webView _executeEditCommand:command argument:argument completion:^(BOOL success) { result = success; done = true; }]; TestWebKitAPI::Util::run(&done); EXPECT_TRUE(result); if (!result) NSLog(@"Failed to execute editing command: ('%@', '%@')", command, argument ?: @""); const NSTimeInterval loggingTimeout = 3; auto startTime = retainPtr([NSDate date]); BOOL hasLoggedWarning = NO; BOOL containsEntries; do { [_webView waitForNextPresentationUpdate]; containsEntries = [self latestEditorStateContains:entries]; if (!hasLoggedWarning && [[NSDate date] timeIntervalSinceDate:startTime.get()] > loggingTimeout) { NSLog(@"Expected %@ to contain %@", self.latestEditorState, entries); hasLoggedWarning = YES; } } while (!containsEntries); } - (BOOL)latestEditorStateContains:(NSDictionary *)entries { NSDictionary *latestEditorState = self.latestEditorState; for (NSString *key in entries) { if (![latestEditorState[key] isEqual:entries[key]]) return NO; } return latestEditorState.count || !entries.count; } #pragma mark - WKUIDelegatePrivate - (void)_webView:(WKWebView *)webView editorStateDidChange:(NSDictionary *)editorState { if (![editorState[@"post-layout-data"] boolValue]) return; if (![self.latestEditorState isEqualToDictionary:editorState]) [_editorStateHistory addObject:editorState]; } @end