| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/web/web_state/ui/crw_context_menu_element_fetcher.h" |
| |
| #import <WebKit/WebKit.h> |
| |
| #import "base/test/ios/wait_util.h" |
| #import "base/time/time.h" |
| #import "ios/testing/scoped_block_swizzler.h" |
| #import "ios/web/js_features/context_menu/context_menu_constants.h" |
| #import "ios/web/public/test/web_view_content_test_util.h" |
| #import "ios/web/test/web_test_with_web_controller.h" |
| #import "ios/web/web_state/ui/crw_web_controller.h" |
| #import "ios/web/web_state/web_state_impl.h" |
| #import "testing/gtest/include/gtest/gtest.h" |
| #import "testing/gtest_mac.h" |
| |
| namespace { |
| // This is the timeout used while waiting for the JavaScript to complete. The |
| // general kWaitForJSCompletionTimeout isn't used because one of the test is |
| // supposed to not complete and so will wait for the whole duration of the |
| // timeout. This constant is smaller to speed tests up. This constant is used in |
| // both the "successful" JavaScript calls and the "failing" JavaScript calls. It |
| // ensures that in the context of this test, the JavaScript completes in the |
| // given timespan (and so it ensures that if the "failing" JavaScript tests |
| // pass, it is because the JavaScript isn't called and not because it didn't |
| // have time to complete). |
| constexpr base::TimeDelta kFetcherJSTimeout = base::Seconds(1); |
| } // namespace |
| |
| namespace web { |
| class CRWContextMenuElementFetcherTest : public WebTestWithWebController { |
| public: |
| void SetUp() override { |
| WebTestWithWebState::SetUp(); |
| WKWebView* web_view = [web_controller() ensureWebViewCreated]; |
| fetcher_ = |
| [[CRWContextMenuElementFetcher alloc] initWithWebView:web_view |
| webState:web_state()]; |
| } |
| |
| // Loads a page containing a link and waits until the link is present on the |
| // page, making sure that the HTML is correctly injected. |
| [[nodiscard]] bool LoadHtmlPage() { |
| NSString* html = |
| @"<html><head>" |
| "<style>body { font-size:14em; }</style>" |
| "<meta name=\"viewport\" content=\"user-scalable=no, width=100\">" |
| "</head><body><p><a id=\"linkID\" " |
| "href=\"http://destination/\">link</a></p></body></html>"; |
| |
| LoadHtml(html); |
| |
| bool element_present = test::WaitForWebViewContainingElement( |
| web_state(), [ElementSelector selectorWithElementID:"linkID"]); |
| if (element_present) { |
| // If the element is present, we still need a small delay to let all the |
| // scripts be injected in the page. |
| base::test::ios::SpinRunLoopWithMinDelay(base::Seconds(0.5)); |
| } |
| return element_present; |
| } |
| |
| CRWContextMenuElementFetcher* GetFetcher() { return fetcher_; } |
| |
| private: |
| std::unique_ptr<ScopedBlockSwizzler> swizzler_; |
| CRWContextMenuElementFetcher* fetcher_; |
| }; |
| |
| // Tests that the fetcher is triggering a callback for one element. |
| TEST_F(CRWContextMenuElementFetcherTest, FetchOneElement) { |
| EXPECT_TRUE(LoadHtmlPage()); |
| |
| CRWContextMenuElementFetcher* fetcher = GetFetcher(); |
| __block bool callback_called = false; |
| [fetcher fetchDOMElementAtPoint:CGPointMake(10, 10) |
| completionHandler:^(const web::ContextMenuParams&) { |
| callback_called = true; |
| }]; |
| |
| EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(kFetcherJSTimeout, ^{ |
| return callback_called; |
| })); |
| } |
| |
| // Tests that cancelled fetches don't trigger callback. |
| TEST_F(CRWContextMenuElementFetcherTest, CancelFetch) { |
| EXPECT_TRUE(LoadHtmlPage()); |
| |
| CRWContextMenuElementFetcher* fetcher = GetFetcher(); |
| __block bool callback_called = false; |
| [fetcher fetchDOMElementAtPoint:CGPointMake(10, 10) |
| completionHandler:^(const web::ContextMenuParams&) { |
| callback_called = true; |
| }]; |
| [fetcher cancelFetches]; |
| |
| // The callback should never be called. |
| EXPECT_FALSE( |
| base::test::ios::WaitUntilConditionOrTimeout(kFetcherJSTimeout, ^{ |
| return callback_called; |
| })); |
| } |
| |
| } // namespace web |