diff options
author | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-08 19:53:40 +0000 |
---|---|---|
committer | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-08 19:53:40 +0000 |
commit | 604f893cf84613c0196657c234b2426b9201d9bd (patch) | |
tree | ee7a877216afa3709af2eac9d1ab3aadcaafad73 /tools | |
parent | b01ee53f686955745f08f3cff14e7417c59f390a (diff) | |
download | chromium_src-604f893cf84613c0196657c234b2426b9201d9bd.zip chromium_src-604f893cf84613c0196657c234b2426b9201d9bd.tar.gz chromium_src-604f893cf84613c0196657c234b2426b9201d9bd.tar.bz2 |
Chrome remote control multipage tests: Add interactions.
The page set .json description defines what kind of interactions (e.g., link
clicks) are possible for a page. The corresponding Web Page Replay .wpr file
must contain replies to the requests sent when the interaction is executed.
This will be used in memory tests (see
http://codereview.chromium.org/11273081/ ).
The top_25_usage.json is a proof of concept page set description adding a couple
of interactions. When it's more complete, the existing tests will be migrated to
use it.
Parts of the code are stolen from nduca@chromium.org (see
http://codereview.chromium.org/11114020/ ).
BUG=158323
Review URL: https://codereview.chromium.org/11369075
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@166734 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/page_sets/top_25.json | 19 | ||||
-rw-r--r-- | tools/telemetry/telemetry/click_to_navigate_interaction.py | 18 | ||||
-rw-r--r-- | tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py | 25 | ||||
-rw-r--r-- | tools/telemetry/telemetry/compound_interaction.py | 17 | ||||
-rw-r--r-- | tools/telemetry/telemetry/compound_interaction_unittest.py | 42 | ||||
-rw-r--r-- | tools/telemetry/telemetry/inspector_page.py | 78 | ||||
-rw-r--r-- | tools/telemetry/telemetry/inspector_page_unittest.py | 27 | ||||
-rw-r--r-- | tools/telemetry/telemetry/page_interaction.py | 37 | ||||
-rw-r--r-- | tools/telemetry/unittest_data/page_with_link.html | 8 |
9 files changed, 240 insertions, 31 deletions
diff --git a/tools/perf/page_sets/top_25.json b/tools/perf/page_sets/top_25.json index 2e23640..7ffa9f9 100644 --- a/tools/perf/page_sets/top_25.json +++ b/tools/perf/page_sets/top_25.json @@ -59,7 +59,24 @@ "url": "http://www.facebook.com/barackobama", "why": "top social,Public profile", "credentials": "facebook", - "scroll_is_infinite": true + "scroll_is_infinite": true, + "stress_memory": { + "action": "compound", + "actions": [ + { + "action": "click_to_navigate", + "selector": "a[href=\"http://www.facebook.com/WomenforObama\"]" + }, + { + "action": "click_to_navigate", + "selector": "a[href=\"http://www.facebook.com/WomenforObama/info\"]" + }, + { + "action": "click_to_navigate", + "selector": "a[href=\"http://www.facebook.com/?ref=tn_tnmn\"]" + } + ] + } }, { "name": "LinkedIn", diff --git a/tools/telemetry/telemetry/click_to_navigate_interaction.py b/tools/telemetry/telemetry/click_to_navigate_interaction.py new file mode 100644 index 0000000..0360fd8 --- /dev/null +++ b/tools/telemetry/telemetry/click_to_navigate_interaction.py @@ -0,0 +1,18 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +from telemetry import page_interaction + +class ClickToNavigateInteraction(page_interaction.PageInteraction): + def __init__(self, attributes=None): + super(ClickToNavigateInteraction, self).__init__(attributes) + + def PerformInteraction(self, page, tab): + assert self.selector + code = 'document.querySelector(\'' + self.selector + '\').click();' + def DoClick(): + tab.runtime.Execute(code) + tab.page.PerformActionAndWaitForNavigate(DoClick) + + +page_interaction.RegisterClass('click_to_navigate', ClickToNavigateInteraction) diff --git a/tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py b/tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py new file mode 100644 index 0000000..f631c2a --- /dev/null +++ b/tools/telemetry/telemetry/click_to_navigate_interaction_unittest.py @@ -0,0 +1,25 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import os + +from telemetry import click_to_navigate_interaction +from telemetry import tab_test_case + +class ClickToNavigateInteractionTest(tab_test_case.TabTestCase): + def testClickToNavigateInteraction(self): + unittest_data_dir = os.path.join(os.path.dirname(__file__), + '..', 'unittest_data') + self._browser.SetHTTPServerDirectory(unittest_data_dir) + self._tab.page.Navigate( + self._browser.http_server.UrlOf('page_with_link.html')) + self._tab.WaitForDocumentReadyStateToBeComplete() + self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'), + '/page_with_link.html') + + data = {'selector': 'a[id="clickme"]'} + i = click_to_navigate_interaction.ClickToNavigateInteraction(data) + i.PerformInteraction({}, self._tab) + + self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'), + '/blank.html') diff --git a/tools/telemetry/telemetry/compound_interaction.py b/tools/telemetry/telemetry/compound_interaction.py new file mode 100644 index 0000000..2ff48b0 --- /dev/null +++ b/tools/telemetry/telemetry/compound_interaction.py @@ -0,0 +1,17 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +from telemetry import page_interaction + +class CompoundInteraction(page_interaction.PageInteraction): + def __init__(self, attributes=None): + super(CompoundInteraction, self).__init__(attributes) + + def PerformInteraction(self, page, tab): + for interaction_data in self.actions: + interaction = page_interaction.FindClassWithName( + interaction_data['action'])(interaction_data) + interaction.PerformInteraction(page, tab) + + +page_interaction.RegisterClass('compound', CompoundInteraction) diff --git a/tools/telemetry/telemetry/compound_interaction_unittest.py b/tools/telemetry/telemetry/compound_interaction_unittest.py new file mode 100644 index 0000000..9b0c9115 --- /dev/null +++ b/tools/telemetry/telemetry/compound_interaction_unittest.py @@ -0,0 +1,42 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from telemetry import compound_interaction +from telemetry import page_interaction +from telemetry import tab_test_case + +class CompoundInteractionTest(tab_test_case.TabTestCase): + interaction1_called = False + interaction2_called = False + + def __init__(self, *args): + super(CompoundInteractionTest, self).__init__(*args) + + def testCompoundInteraction(self): + + class MockInteraction1(page_interaction.PageInteraction): + def PerformInteraction(self, page, tab): + CompoundInteractionTest.interaction1_called = True + + class MockInteraction2(page_interaction.PageInteraction): + def PerformInteraction(self, page, tab): + CompoundInteractionTest.interaction2_called = True + + page_interaction.RegisterClass('mock1', MockInteraction1) + page_interaction.RegisterClass('mock2', MockInteraction2) + + i = compound_interaction.CompoundInteraction({ + 'action': 'compound', + 'actions': [ + { + 'action': 'mock1' + }, + { + 'action': 'mock2' + } + ] + }) + i.PerformInteraction({}, self._tab) + self.assertTrue(CompoundInteractionTest.interaction1_called) + self.assertTrue(CompoundInteractionTest.interaction2_called) diff --git a/tools/telemetry/telemetry/inspector_page.py b/tools/telemetry/telemetry/inspector_page.py index a879dcf..b37d330 100644 --- a/tools/telemetry/telemetry/inspector_page.py +++ b/tools/telemetry/telemetry/inspector_page.py @@ -13,53 +13,71 @@ class InspectorPage(object): 'Page', self._OnNotification, self._OnClose) - self._pending_navigate_url = None + self._navigation_pending = False def _OnNotification(self, msg): logging.debug('Notification: %s', json.dumps(msg, indent=2)) - if msg['method'] == 'Page.frameNavigated' and self._pending_navigate_url: + if msg['method'] == 'Page.frameNavigated' and self._navigation_pending: url = msg['params']['frame']['url'] if not url == 'chrome://newtab/': - # Marks the navigation as complete and unblocks the navigate call. - self._pending_navigate_url = None + # Marks the navigation as complete and unblocks the + # PerformActionAndWaitForNavigate call. + self._navigation_pending = False def _OnClose(self): pass - def Navigate(self, url, timeout=60): - """Navigates to url""" + def PerformActionAndWaitForNavigate(self, action_function, timeout=60): + """Executes action_function, and waits for the navigation to complete. + + action_function is expect to result in a navigation. This function returns + when the navigation is complete or when the timeout has been exceeded. + """ + # Turn on notifications. We need them to get the Page.frameNavigated event. request = { - 'method': 'Page.enable' - } + 'method': 'Page.enable' + } res = self._inspector_backend.SyncRequest(request, timeout) assert len(res['result'].keys()) == 0 - # Navigate the page. However, there seems to be a bug in chrome devtools - # protocol where the request id for this event gets held on the browser side - # pretty much indefinitely. - # - # So, instead of waiting for the event to actually complete, wait for the - # Page.frameNavigated event. - request = { - 'method': 'Page.navigate', - 'params': { - 'url': url, - } - } - res = self._inspector_backend.SendAndIgnoreResponse(request) + def DisablePageNotifications(): + request = { + 'method': 'Page.disable' + } + res = self._inspector_backend.SyncRequest(request, timeout) + assert len(res['result'].keys()) == 0 + + self._navigation_pending = True + try: + action_function() + except: + DisablePageNotifications() + raise - self._pending_navigate_url = url def IsNavigationDone(time_left): self._inspector_backend.DispatchNotifications(time_left) - return self._pending_navigate_url == None - + return not self._navigation_pending util.WaitFor(IsNavigationDone, timeout, pass_time_left_to_func=True) - # Turn off notifications. - request = { - 'method': 'Page.disable' - } - res = self._inspector_backend.SyncRequest(request, timeout) - assert len(res['result'].keys()) == 0 + DisablePageNotifications() + + def Navigate(self, url, timeout=60): + """Navigates to url""" + + def DoNavigate(): + # Navigate the page. However, there seems to be a bug in chrome devtools + # protocol where the request id for this event gets held on the browser + # side pretty much indefinitely. + # + # So, instead of waiting for the event to actually complete, wait for the + # Page.frameNavigated event. + request = { + 'method': 'Page.navigate', + 'params': { + 'url': url, + } + } + self._inspector_backend.SendAndIgnoreResponse(request) + self.PerformActionAndWaitForNavigate(DoNavigate, timeout) diff --git a/tools/telemetry/telemetry/inspector_page_unittest.py b/tools/telemetry/telemetry/inspector_page_unittest.py index fee527a..33c476e 100644 --- a/tools/telemetry/telemetry/inspector_page_unittest.py +++ b/tools/telemetry/telemetry/inspector_page_unittest.py @@ -1,9 +1,15 @@ # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import os + from telemetry import tab_test_case class InspectorPageTest(tab_test_case.TabTestCase): + def __init__(self, *args): + super(InspectorPageTest, self).__init__(*args) + self._custom_action_called = False + def testPageNavigateToNormalUrl(self): self._tab.page.Navigate('http://www.google.com') self._tab.WaitForDocumentReadyStateToBeComplete() @@ -17,3 +23,24 @@ class InspectorPageTest(tab_test_case.TabTestCase): def testPageNavigateToImpossibleURL(self): self._tab.page.Navigate('http://23f09f0f9fsdflajsfaldfkj2f3f.com') self._tab.WaitForDocumentReadyStateToBeComplete() + + def testCustomActionToNavigate(self): + unittest_data_dir = os.path.join(os.path.dirname(__file__), + '..', 'unittest_data') + self._browser.SetHTTPServerDirectory(unittest_data_dir) + self._tab.page.Navigate( + self._browser.http_server.UrlOf('page_with_link.html')) + self._tab.WaitForDocumentReadyStateToBeComplete() + self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'), + '/page_with_link.html') + + self._custom_action_called = False + def CustomAction(): + self._custom_action_called = True + self._tab.runtime.Execute('document.getElementById("clickme").click();') + + self._tab.page.PerformActionAndWaitForNavigate(CustomAction) + + self.assertTrue(self._custom_action_called) + self.assertEquals(self._tab.runtime.Evaluate('document.location.pathname;'), + '/blank.html') diff --git a/tools/telemetry/telemetry/page_interaction.py b/tools/telemetry/telemetry/page_interaction.py new file mode 100644 index 0000000..108db76 --- /dev/null +++ b/tools/telemetry/telemetry/page_interaction.py @@ -0,0 +1,37 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +class PageInteractionNotSupported(Exception): + pass + +class PageInteractionFailed(Exception): + pass + +class PageInteraction(object): + """Represents an interaction that a user might try to perform to a page.""" + def __init__(self, attributes=None): + if attributes: + for k, v in attributes.iteritems(): + setattr(self, k, v) + + def CustomizeBrowserOptions(self, options): + """Override to add test-specific options to the BrowserOptions object""" + pass + + def PerformInteraction(self, page, tab): + raise NotImplementedError() + + def CleanUp(self, page, tab): + pass + +_page_interaction_classes = {} +def GetAllClasses(): + return list(_page_interaction_classes.values()) + +def FindClassWithName(name): + return _page_interaction_classes.get(name) + +def RegisterClass(name, interaction_class): + assert name not in _page_interaction_classes + _page_interaction_classes[name] = interaction_class diff --git a/tools/telemetry/unittest_data/page_with_link.html b/tools/telemetry/unittest_data/page_with_link.html new file mode 100644 index 0000000..dc3c008 --- /dev/null +++ b/tools/telemetry/unittest_data/page_with_link.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML> +<html> +<head> +</head> +<body> +<a id="clickme" href="blank.html">Click me</a> +</body> +</html> |