diff options
author | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-28 21:24:34 +0000 |
---|---|---|
committer | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-28 21:24:34 +0000 |
commit | 50cdc732caacead0d4236716c43342ae14e366f3 (patch) | |
tree | bfa49fd0e3ff3a35e16a8201544ed9709136c9df /chrome_frame | |
parent | e55a7ddf8a95cd64c620f4536d641fede75d51d0 (diff) | |
download | chromium_src-50cdc732caacead0d4236716c43342ae14e366f3.zip chromium_src-50cdc732caacead0d4236716c43342ae14e366f3.tar.gz chromium_src-50cdc732caacead0d4236716c43342ae14e366f3.tar.bz2 |
Add chrome frame tests for common navigation cases to ensure IE still works.
BUG=none
TEST=none
Review url: http://codereview.chromium.org/2173002
Review URL: http://codereview.chromium.org/2374002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48527 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r-- | chrome_frame/chrome_frame.gyp | 1 | ||||
-rw-r--r-- | chrome_frame/test/chrome_frame_test_utils.cc | 14 | ||||
-rw-r--r-- | chrome_frame/test/chrome_frame_test_utils.h | 13 | ||||
-rw-r--r-- | chrome_frame/test/data/no_interference/javascript_redirect.html | 11 | ||||
-rw-r--r-- | chrome_frame/test/data/no_interference/link.html | 5 | ||||
-rw-r--r-- | chrome_frame/test/no_interference_test.cc | 138 | ||||
-rw-r--r-- | chrome_frame/test/simulate_input.cc | 39 | ||||
-rw-r--r-- | chrome_frame/test/simulate_input.h | 5 | ||||
-rw-r--r-- | chrome_frame/test/test_mock_with_web_server.cc | 48 | ||||
-rw-r--r-- | chrome_frame/test/test_mock_with_web_server.h | 13 |
10 files changed, 232 insertions, 55 deletions
diff --git a/chrome_frame/chrome_frame.gyp b/chrome_frame/chrome_frame.gyp index 141a88e..534dcc2 100644 --- a/chrome_frame/chrome_frame.gyp +++ b/chrome_frame/chrome_frame.gyp @@ -229,6 +229,7 @@ 'test/chrome_frame_automation_mock.h', 'test/http_server.cc', 'test/http_server.h', + 'test/no_interference_test.cc', 'test/proxy_factory_mock.cc', 'test/proxy_factory_mock.h', 'test/run_all_unittests.cc', diff --git a/chrome_frame/test/chrome_frame_test_utils.cc b/chrome_frame/test/chrome_frame_test_utils.cc index 5ae558b..62be84e 100644 --- a/chrome_frame/test/chrome_frame_test_utils.cc +++ b/chrome_frame/test/chrome_frame_test_utils.cc @@ -891,4 +891,18 @@ FilePath GetProfilePathForIE() { return profile_path; } +void DelaySendExtendedKeysEnter(TimedMsgLoop* loop, int delay, char c, + int repeat, simulate_input::Modifier mod) { + const unsigned int kInterval = 25; + unsigned int next_delay = delay; + for (int i = 0; i < repeat; i++) { + loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( + simulate_input::SendExtendedKey, c, mod), next_delay); + next_delay += kInterval; + } + + loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( + simulate_input::SendCharA, VK_RETURN, simulate_input::NONE), next_delay); +} + } // namespace chrome_frame_test diff --git a/chrome_frame/test/chrome_frame_test_utils.h b/chrome_frame/test/chrome_frame_test_utils.h index 022b057..b162214 100644 --- a/chrome_frame/test/chrome_frame_test_utils.h +++ b/chrome_frame/test/chrome_frame_test_utils.h @@ -25,6 +25,7 @@ #include "chrome_frame/test/simulate_input.h" #include "chrome_frame/test/window_watchdog.h" #include "chrome_frame/utils.h" +#include "gmock/gmock.h" // Include without path to make GYP build see it. #include "chrome_tab.h" // NOLINT @@ -345,6 +346,18 @@ std::wstring GetExeVersion(const std::wstring& exe_path); // Returns the version of Internet Explorer on the machine. IEVersion GetInstalledIEVersion(); +// Posts a delayed task to send an extended keystroke |repeat| times with an +// optional modifier via SendInput. Following this, the enter key is sent. +void DelaySendExtendedKeysEnter(TimedMsgLoop* loop, int delay, char c, + int repeat, simulate_input::Modifier mod); + +// Returns an action which posts a delayed task that sends the given +// scan code via SendInput. +ACTION_P4(DelaySendScanCode, loop, delay, c, mod) { + loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( + simulate_input::SendScanCode, c, mod), delay); +} + // A convenience class to close all open IE windows at the end // of a scope. It's more convenient to do it this way than to // explicitly call chrome_frame_test::CloseAllIEWindows at the diff --git a/chrome_frame/test/data/no_interference/javascript_redirect.html b/chrome_frame/test/data/no_interference/javascript_redirect.html new file mode 100644 index 0000000..5e29ab1 --- /dev/null +++ b/chrome_frame/test/data/no_interference/javascript_redirect.html @@ -0,0 +1,11 @@ +<html> + <head> + <script type="text/javascript"> + window.onload = function() { + var url = "" + window.location; + window.location = url.substring(0, url.lastIndexOf("/") + 1) + + "empty.html"; + } + </script> + </head> +</html>
\ No newline at end of file diff --git a/chrome_frame/test/data/no_interference/link.html b/chrome_frame/test/data/no_interference/link.html new file mode 100644 index 0000000..d84da5b --- /dev/null +++ b/chrome_frame/test/data/no_interference/link.html @@ -0,0 +1,5 @@ +<html> + <body> + <a href="empty.html">Empty page</a> + </body> +</html>
\ No newline at end of file diff --git a/chrome_frame/test/no_interference_test.cc b/chrome_frame/test/no_interference_test.cc index acd1d5c..f560adb 100644 --- a/chrome_frame/test/no_interference_test.cc +++ b/chrome_frame/test/no_interference_test.cc @@ -64,8 +64,6 @@ class NoInterferenceTest : public ChromeFrameTestWithWebServer { // Launches IE and navigates to |url|, then waits until receiving a quit // message or the timeout is exceeded. void LaunchIEAndNavigate(const std::wstring& url) { - CloseIeAtEndOfScope last_resort_close_ie; - EXPECT_CALL(mock_, OnQuit()) .Times(testing::AtMost(1)) .WillOnce(QUIT_LOOP(loop_)); @@ -76,6 +74,7 @@ class NoInterferenceTest : public ChromeFrameTestWithWebServer { ASSERT_TRUE(mock_.web_browser2() != NULL); loop_.RunFor(kChromeFrameLongNavigationTimeoutInSeconds); + mock_.Uninitialize(); } const std::wstring GetTestUrl(const wchar_t* relative_path) { @@ -84,46 +83,153 @@ class NoInterferenceTest : public ChromeFrameTestWithWebServer { return UTF8ToWide(server_.Resolve(path.c_str()).spec()); } + const std::wstring empty_page_url() { + return GetTestUrl(L"empty.html"); + } + + // Returns the url for a page with a single link, which points to the + // empty page. + const std::wstring link_page_url() { + return GetTestUrl(L"link.html"); + } + + CloseIeAtEndOfScope last_resort_close_ie; chrome_frame_test::TimedMsgLoop loop_; - ComStackObjectWithUninitialize< - testing::StrictMock<MockWebBrowserEventSink> > mock_; + CComObjectStackEx<testing::StrictMock<MockWebBrowserEventSink> > mock_; }; ACTION_P(ExpectIERendererWindowHasFocus, mock) { mock->ExpectIERendererWindowHasFocus(); } -// This tests that a new IE renderer window has focus. -TEST_F(NoInterferenceTest, SimpleFocus) { - const std::wstring kEmptyFileUrl = GetTestUrl(L"empty.html"); - mock_.ExpectNavigationAndSwitch(kEmptyFileUrl); +ACTION_P6(DelaySendMouseClickToIE, mock, loop, delay, x, y, button) { + loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(mock, + &MockWebBrowserEventSink::SendMouseClickToIE, x, y, button), delay); +} + +ACTION_P2(OpenContextMenu, loop, delay) { + loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( + simulate_input::SendScanCode, VK_F10, simulate_input::SHIFT), delay); +} + +ACTION_P3(SelectItem, loop, delay, index) { + chrome_frame_test::DelaySendExtendedKeysEnter(loop, delay, VK_DOWN, index + 1, + simulate_input::NONE); +} - EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(kEmptyFileUrl))) +// A new IE renderer window should have focus. +TEST_F(NoInterferenceTest, SimpleFocus) { + mock_.ExpectNavigationInIE(empty_page_url()); + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) .WillOnce(testing::DoAll( ExpectIERendererWindowHasFocus(&mock_), VerifyAddressBarUrl(&mock_), CloseBrowserMock(&mock_))); - LaunchIEAndNavigate(kEmptyFileUrl); + LaunchIEAndNavigate(empty_page_url()); } -// This tests that window.open does not get intercepted by Chrome Frame. +// Javascript window.open should open a new window with an IE renderer. TEST_F(NoInterferenceTest, FLAKY_JavascriptWindowOpen) { - const std::wstring kEmptyFileUrl = GetTestUrl(L"empty.html"); const std::wstring kWindowOpenUrl = GetTestUrl(L"window_open.html"); ComStackObjectWithUninitialize< testing::StrictMock<MockWebBrowserEventSink> > new_window_mock; - mock_.ExpectNavigationAndSwitch(kWindowOpenUrl); + mock_.ExpectNavigationInIE(kWindowOpenUrl); EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(kWindowOpenUrl))); - mock_.ExpectNewWindow(&new_window_mock); - EXPECT_CALL(new_window_mock, OnIELoad(testing::StrCaseEq(kEmptyFileUrl))) - .WillOnce(CloseBrowserMock(&new_window_mock)); + mock_.ExpectNewWindowWithIE(empty_page_url(), &new_window_mock); + EXPECT_CALL(new_window_mock, OnIELoad(testing::StrCaseEq(empty_page_url()))) + .WillOnce(testing::DoAll( + VerifyAddressBarUrl(&new_window_mock), + CloseBrowserMock(&new_window_mock))); EXPECT_CALL(new_window_mock, OnQuit()) .WillOnce(CloseBrowserMock(&mock_)); LaunchIEAndNavigate(kWindowOpenUrl); } +// Redirecting with window.location in Javascript should work. +TEST_F(NoInterferenceTest, JavascriptRedirect) { + const std::wstring kRedirectUrl = GetTestUrl(L"javascript_redirect.html"); + mock_.ExpectNavigationInIE(kRedirectUrl); + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(kRedirectUrl))) + .WillOnce(VerifyAddressBarUrl(&mock_)); + + mock_.ExpectNavigationInIE(empty_page_url()); + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) + .WillOnce(testing::DoAll( + VerifyAddressBarUrl(&mock_), + CloseBrowserMock(&mock_))); + + LaunchIEAndNavigate(kRedirectUrl); +} + +TEST_F(NoInterferenceTest, FLAKY_FollowLink) { + mock_.ExpectNavigationInIE(link_page_url()); + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url()))) + .WillOnce(testing::DoAll( + DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1, + simulate_input::LEFT), + DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE), + DelaySendScanCode(&loop_, 1000, VK_RETURN, simulate_input::NONE))); + + mock_.ExpectNavigationInIE(empty_page_url()); + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) + .WillOnce(testing::DoAll( + VerifyAddressBarUrl(&mock_), + CloseBrowserMock(&mock_))); + + LaunchIEAndNavigate(link_page_url()); +} + +TEST_F(NoInterferenceTest, FLAKY_SelectContextMenuOpen) { + mock_.ExpectNavigationInIE(link_page_url()); + // Focus the renderer window by clicking and then tab once to highlight the + // link. + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url()))) + .WillOnce(testing::DoAll( + DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1, + simulate_input::LEFT), + DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE), + OpenContextMenu(&loop_, 1000), + SelectItem(&loop_, 1500, 0))); + + mock_.ExpectNavigationInIE(empty_page_url()); + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(empty_page_url()))) + .WillOnce(testing::DoAll( + VerifyAddressBarUrl(&mock_), + CloseBrowserMock(&mock_))); + + LaunchIEAndNavigate(link_page_url()); +} + +TEST_F(NoInterferenceTest, FLAKY_SelectContextMenuOpenInNewWindow) { + ComStackObjectWithUninitialize< + testing::StrictMock<MockWebBrowserEventSink> > new_window_mock; + int open_new_window_index = 2; + if (chrome_frame_test::GetInstalledIEVersion() == IE_6) + open_new_window_index = 1; + + // Focus the renderer window by clicking and then tab once to highlight the + // link. + mock_.ExpectNavigationInIE(link_page_url()); + EXPECT_CALL(mock_, OnIELoad(testing::StrCaseEq(link_page_url()))) + .WillOnce(testing::DoAll( + DelaySendMouseClickToIE(&mock_, &loop_, 0, 1, 1, + simulate_input::LEFT), + DelaySendScanCode(&loop_, 500, VK_TAB, simulate_input::NONE), + OpenContextMenu(&loop_, 1000), + SelectItem(&loop_, 1500, open_new_window_index))); + + mock_.ExpectNewWindowWithIE(empty_page_url(), &new_window_mock); + // TODO(kkania): Verifying the address bar is flaky with this, at least + // on XP ie6. Fix. + EXPECT_CALL(new_window_mock, OnIELoad(testing::StrCaseEq(empty_page_url()))) + .WillOnce(CloseBrowserMock(&new_window_mock)); + EXPECT_CALL(new_window_mock, OnQuit()).WillOnce(CloseBrowserMock(&mock_)); + + LaunchIEAndNavigate(link_page_url()); +} + } // namespace
\ No newline at end of file diff --git a/chrome_frame/test/simulate_input.cc b/chrome_frame/test/simulate_input.cc index 411f72e..68d8edc 100644 --- a/chrome_frame/test/simulate_input.cc +++ b/chrome_frame/test/simulate_input.cc @@ -192,29 +192,14 @@ void SetKeyboardFocusToWindow(HWND window) { SendMouseClick(window, 1, 1, LEFT); } -void SendMouseClick(HWND window, int x, int y, MouseButton button) { - if (!IsWindow(window)) { - NOTREACHED() << "Invalid window handle."; - return; - } - - HWND top_level_window = window; - if (!IsTopLevelWindow(top_level_window)) { - top_level_window = GetAncestor(window, GA_ROOT); - } - - ForceSetForegroundWindow(top_level_window); - - POINT cursor_position = {x, y}; - ClientToScreen(window, &cursor_position); - +void SendMouseClick(int x, int y, MouseButton button) { // TODO(joshia): Fix this. GetSystemMetrics(SM_CXSCREEN) will // retrieve screen size of the primarary monitor only. And monitors // arrangement could be pretty arbitrary. double screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1; double screen_height = ::GetSystemMetrics(SM_CYSCREEN) - 1; - double location_x = cursor_position.x * (65535.0f / screen_width); - double location_y = cursor_position.y * (65535.0f / screen_height); + double location_x = x * (65535.0f / screen_width); + double location_y = y * (65535.0f / screen_height); // Take advantage of button flag bitmask layout unsigned int button_flag = MOUSEEVENTF_LEFTDOWN << (button + button); @@ -237,6 +222,24 @@ void SendMouseClick(HWND window, int x, int y, MouseButton button) { ::SendInput(1, &input_info, sizeof(INPUT)); } +void SendMouseClick(HWND window, int x, int y, MouseButton button) { + if (!IsWindow(window)) { + NOTREACHED() << "Invalid window handle."; + return; + } + + HWND top_level_window = window; + if (!IsTopLevelWindow(top_level_window)) { + top_level_window = GetAncestor(window, GA_ROOT); + } + + ForceSetForegroundWindow(top_level_window); + + POINT cursor_position = {x, y}; + ClientToScreen(window, &cursor_position); + SendMouseClick(cursor_position.x, cursor_position.y, button); +} + void SendExtendedKey(WORD key, Modifier modifiers) { SendMnemonic(key, modifiers, true, false); } diff --git a/chrome_frame/test/simulate_input.h b/chrome_frame/test/simulate_input.h index 135c310..fab22a8 100644 --- a/chrome_frame/test/simulate_input.h +++ b/chrome_frame/test/simulate_input.h @@ -37,8 +37,11 @@ void SetKeyboardFocusToWindow(HWND window); void SendMnemonic(WORD mnemonic_char, Modifier modifiers, bool extended, bool unicode); -// Sends a mouse click to the window passed in. +// Sends a mouse click to the desktop. enum MouseButton { LEFT, RIGHT, MIDDLE, X }; +void SendMouseClick(int x, int y, MouseButton button); +// Sends a mouse click to the window passed in, after ensuring that the window +// is in the foreground. void SendMouseClick(HWND window, int x, int y, MouseButton button); // Translates a single char to a virtual key. diff --git a/chrome_frame/test/test_mock_with_web_server.cc b/chrome_frame/test/test_mock_with_web_server.cc index f869bb7..174311d 100644 --- a/chrome_frame/test/test_mock_with_web_server.cc +++ b/chrome_frame/test/test_mock_with_web_server.cc @@ -147,6 +147,34 @@ ExpectationSet MockWebBrowserEventSink::ExpectNewWindow( return new_window; } +ExpectationSet MockWebBrowserEventSink::ExpectNavigationInIE( + const std::wstring& url) { + testing::InSequence sequence; + ExpectationSet navigation; + navigation += EXPECT_CALL(*this, OnBeforeNavigate2(_, + testing::Field(&VARIANT::bstrVal, + testing::StrCaseEq(url)), _, _, _, _, _)); + navigation += EXPECT_CALL(*this, OnFileDownload(VARIANT_TRUE, _)) + .Times(testing::AnyNumber()); + navigation += EXPECT_CALL(*this, OnNavigateComplete2(_, + testing::Field(&VARIANT::bstrVal, + testing::StrCaseEq(url)))); + return navigation; +} + +ExpectationSet MockWebBrowserEventSink::ExpectNewWindowWithIE( + const std::wstring& url, MockWebBrowserEventSink* new_window_mock) { + DCHECK(new_window_mock); + ExpectationSet new_window; + new_window += EXPECT_CALL(*this, OnNewWindow3(_, _, _, _, _)); + new_window += EXPECT_CALL(*this, OnNewBrowserWindow(_, _)) + .WillOnce(testing::WithArgs<0>(testing::Invoke(CreateFunctor( + new_window_mock, &MockWebBrowserEventSink::Attach)))); + + new_window_mock->ExpectNavigationInIE(url); + return new_window; +} + } // namespace chrome_frame_test ACTION_P3(DelayCloseBrowserMock, loop, delay, mock) { @@ -180,27 +208,13 @@ ACTION_P4(DelaySendChar, loop, delay, c, mod) { simulate_input::SendCharA, c, mod), delay); } -ACTION_P4(DelaySendScanCode, loop, delay, c, mod) { +ACTION_P3(DelaySendString, loop, delay, str) { loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( - simulate_input::SendScanCode, c, mod), delay); + simulate_input::SendStringW, str), delay); } ACTION_P5(SendExtendedKeysEnter, loop, delay, c, repeat, mod) { - const unsigned int kInterval = 25; - unsigned int next_delay = delay; - for (int i = 0; i < repeat; i++) { - loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( - simulate_input::SendExtendedKey, c, mod), next_delay); - next_delay += kInterval; - } - - loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( - simulate_input::SendCharA, VK_RETURN, simulate_input::NONE), next_delay); -} - -ACTION_P3(DelaySendString, loop, delay, str) { - loop->PostDelayedTask(FROM_HERE, NewRunnableFunction( - simulate_input::SendStringW, str), delay); + chrome_frame_test::DelaySendExtendedKeysEnter(loop, delay, c, repeat, mod); } ACTION(DoCloseWindow) { diff --git a/chrome_frame/test/test_mock_with_web_server.h b/chrome_frame/test/test_mock_with_web_server.h index 53fccb1..2d71721 100644 --- a/chrome_frame/test/test_mock_with_web_server.h +++ b/chrome_frame/test/test_mock_with_web_server.h @@ -75,15 +75,22 @@ class MockWebBrowserEventSink : public chrome_frame_test::WebBrowserEventSink { MOCK_METHOD2(OnWindowDetected, void (HWND hwnd, // NOLINT const std::string& caption)); - // Test expectations + // Test expectations for general navigations. ExpectationSet ExpectNavigationCardinality(const std::wstring& url, testing::Cardinality cardinality); ExpectationSet ExpectNavigation(const std::wstring& url); ExpectationSet ExpectNavigationAndSwitch(const std::wstring& url); ExpectationSet ExpectNavigationAndSwitchSequence(const std::wstring& url); ExpectationSet ExpectNewWindow(MockWebBrowserEventSink* new_window_mock); - ExpectationSet MockWebBrowserEventSink::ExpectNavigationSequenceForAnchors( - const std::wstring& url); + ExpectationSet ExpectNavigationSequenceForAnchors(const std::wstring& url); + + // Test expectations for navigations with an IE renderer. + // Expect one navigation to occur. + ExpectationSet ExpectNavigationInIE(const std::wstring& url); + // Expect a new window to be opened to |url|. Set |new_window_mock| as the new + // window. + ExpectationSet ExpectNewWindowWithIE( + const std::wstring& url, MockWebBrowserEventSink* new_window_mock); }; ACTION_P(CloseBrowserMock, mock) { |