Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / tools / perf / page_sets / polymer.py
blobec3316f5a0eec373b0322f6b3a459d49276005b6
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 from telemetry.page import page as page_module
5 from telemetry.page import shared_page_state
6 from telemetry import story
9 class PolymerPage(page_module.Page):
11 def __init__(self, url, page_set, run_no_page_interactions):
12 """ Base class for all polymer pages.
14 Args:
15 run_no_page_interactions: whether the page will run any interactions after
16 navigate steps.
17 """
18 super(PolymerPage, self).__init__(
19 url=url,
20 shared_page_state_class=shared_page_state.SharedMobilePageState,
21 page_set=page_set)
22 self.script_to_evaluate_on_commit = '''
23 document.addEventListener("polymer-ready", function() {
24 window.__polymer_ready = true;
25 });
26 '''
27 self._run_no_page_interactions = run_no_page_interactions
29 def RunPageInteractions(self, action_runner):
30 # If a polymer page wants to customize its actions, it should
31 # override the PerformPageInteractions method instead of this method.
32 if self._run_no_page_interactions:
33 return
34 self.PerformPageInteractions(action_runner)
36 def PerformPageInteractions(self, action_runner):
37 """ Override this to perform actions after the page has navigated. """
38 pass
40 def RunNavigateSteps(self, action_runner):
41 super(PolymerPage, self).RunNavigateSteps(action_runner)
42 action_runner.WaitForJavaScriptCondition(
43 'window.__polymer_ready')
46 class PolymerCalculatorPage(PolymerPage):
48 def __init__(self, page_set, run_no_page_interactions):
49 super(PolymerCalculatorPage, self).__init__(
50 url=('http://www.polymer-project.org/components/paper-calculator/'
51 'demo.html'),
52 page_set=page_set, run_no_page_interactions=run_no_page_interactions)
54 def PerformPageInteractions(self, action_runner):
55 self.TapButton(action_runner)
56 self.SlidePanel(action_runner)
58 def TapButton(self, action_runner):
59 with action_runner.CreateInteraction('PolymerAnimation', repeatable=True):
60 action_runner.TapElement(element_function='''
61 document.querySelector(
62 'body /deep/ #outerPanels'
63 ).querySelector(
64 '#standard'
65 ).shadowRoot.querySelector(
66 'paper-calculator-key[label="5"]'
67 )''')
68 action_runner.Wait(2)
70 def SlidePanel(self, action_runner):
71 # only bother with this interaction if the drawer is hidden
72 opened = action_runner.EvaluateJavaScript('''
73 (function() {
74 var outer = document.querySelector("body /deep/ #outerPanels");
75 return outer.opened || outer.wideMode;
76 }());''')
77 if not opened:
78 with action_runner.CreateInteraction('PolymerAnimation', repeatable=True):
79 action_runner.SwipeElement(
80 left_start_ratio=0.1, top_start_ratio=0.2,
81 direction='left', distance=300, speed_in_pixels_per_second=5000,
82 element_function='''
83 document.querySelector(
84 'body /deep/ #outerPanels'
85 ).querySelector(
86 '#advanced'
87 ).shadowRoot.querySelector(
88 '.handle-bar'
89 )''')
90 action_runner.WaitForJavaScriptCondition('''
91 var outer = document.querySelector("body /deep/ #outerPanels");
92 outer.opened || outer.wideMode;''')
95 class PolymerShadowPage(PolymerPage):
97 def __init__(self, page_set, run_no_page_interactions):
98 super(PolymerShadowPage, self).__init__(
99 url='http://www.polymer-project.org/components/paper-shadow/demo.html',
100 page_set=page_set, run_no_page_interactions=run_no_page_interactions)
102 def PerformPageInteractions(self, action_runner):
103 with action_runner.CreateInteraction('ScrollAndShadowAnimation'):
104 action_runner.ExecuteJavaScript(
105 "document.getElementById('fab').scrollIntoView()")
106 action_runner.Wait(5)
107 self.AnimateShadow(action_runner, 'card')
108 #FIXME(wiltzius) disabling until this issue is fixed:
109 # https://github.com/Polymer/paper-shadow/issues/12
110 #self.AnimateShadow(action_runner, 'fab')
112 def AnimateShadow(self, action_runner, eid):
113 for i in range(1, 6):
114 action_runner.ExecuteJavaScript(
115 'document.getElementById("{0}").z = {1}'.format(eid, i))
116 action_runner.Wait(1)
119 class PolymerSampler(PolymerPage):
121 def __init__(self, page_set, anchor, run_no_page_interactions,
122 scrolling_page=False):
123 """Page exercising interactions with a single Paper Sampler subpage.
125 Args:
126 page_set: Page set to inforporate this page into.
127 anchor: string indicating which subpage to load (matches the element
128 type that page is displaying)
129 scrolling_page: Whether scrolling the content pane is relevant to this
130 content page or not.
132 super(PolymerSampler, self).__init__(
133 url=('http://www.polymer-project.org/components/%s/demo.html' % anchor),
134 page_set=page_set, run_no_page_interactions=run_no_page_interactions)
135 self.scrolling_page = scrolling_page
136 self.iframe_js = 'document'
138 def RunNavigateSteps(self, action_runner):
139 super(PolymerSampler, self).RunNavigateSteps(action_runner)
140 waitForLoadJS = """
141 window.Polymer.whenPolymerReady(function() {
142 %s.contentWindow.Polymer.whenPolymerReady(function() {
143 window.__polymer_ready = true;
146 """ % self.iframe_js
147 action_runner.ExecuteJavaScript(waitForLoadJS)
148 action_runner.WaitForJavaScriptCondition(
149 'window.__polymer_ready')
151 def PerformPageInteractions(self, action_runner):
152 #TODO(wiltzius) Add interactions for input elements and shadow pages
153 if self.scrolling_page:
154 # Only bother scrolling the page if its been marked as worthwhile
155 self.ScrollContentPane(action_runner)
156 self.TouchEverything(action_runner)
158 def ScrollContentPane(self, action_runner):
159 element_function = (self.iframe_js + '.querySelector('
160 '"core-scroll-header-panel").$.mainContainer')
161 with action_runner.CreateInteraction('Scroll_Page', repeatable=True):
162 action_runner.ScrollElement(use_touch=True,
163 direction='down',
164 distance='900',
165 element_function=element_function)
166 with action_runner.CreateInteraction('Scroll_Page', repeatable=True):
167 action_runner.ScrollElement(use_touch=True,
168 direction='up',
169 distance='900',
170 element_function=element_function)
172 def TouchEverything(self, action_runner):
173 tappable_types = [
174 'paper-button',
175 'paper-checkbox',
176 'paper-fab',
177 'paper-icon-button',
178 # crbug.com/394756
179 # 'paper-radio-button',
180 'paper-tab',
181 'paper-toggle-button',
182 'x-shadow',
184 for tappable_type in tappable_types:
185 self.DoActionOnWidgetType(action_runner, tappable_type, self.TapWidget)
186 swipeable_types = ['paper-slider']
187 for swipeable_type in swipeable_types:
188 self.DoActionOnWidgetType(action_runner, swipeable_type, self.SwipeWidget)
190 def DoActionOnWidgetType(self, action_runner, widget_type, action_function):
191 # Find all widgets of this type, but skip any that are disabled or are
192 # currently active as they typically don't produce animation frames.
193 element_list_query = (self.iframe_js +
194 ('.querySelectorAll("body %s:not([disabled]):'
195 'not([active])")' % widget_type))
196 roles_count_query = element_list_query + '.length'
197 for i in range(action_runner.EvaluateJavaScript(roles_count_query)):
198 element_query = element_list_query + ("[%d]" % i)
199 if action_runner.EvaluateJavaScript(
200 element_query + '.offsetParent != null'):
201 # Only try to tap on visible elements (offsetParent != null)
202 action_runner.ExecuteJavaScript(element_query + '.scrollIntoView()')
203 action_runner.Wait(1) # wait for page to settle after scrolling
204 action_function(action_runner, element_query)
206 def TapWidget(self, action_runner, element_function):
207 with action_runner.CreateInteraction('Tap_Widget', repeatable=True):
208 action_runner.TapElement(element_function=element_function)
209 action_runner.Wait(1) # wait for e.g. animations on the widget
211 def SwipeWidget(self, action_runner, element_function):
212 with action_runner.CreateInteraction('Swipe_Widget'):
213 action_runner.SwipeElement(element_function=element_function,
214 left_start_ratio=0.75,
215 speed_in_pixels_per_second=300)
218 class PolymerPageSet(story.StorySet):
220 def __init__(self, run_no_page_interactions=False):
221 super(PolymerPageSet, self).__init__(
222 archive_data_file='data/polymer.json',
223 cloud_storage_bucket=story.PUBLIC_BUCKET)
225 self.AddStory(PolymerCalculatorPage(self, run_no_page_interactions))
226 self.AddStory(PolymerShadowPage(self, run_no_page_interactions))
228 # Polymer Sampler subpages that are interesting to tap / swipe elements on
229 TAPPABLE_PAGES = [
230 'paper-button',
231 'paper-checkbox',
232 'paper-fab',
233 'paper-icon-button',
234 # crbug.com/394756
235 # 'paper-radio-button',
236 #FIXME(wiltzius) Disabling x-shadow until this issue is fixed:
237 # https://github.com/Polymer/paper-shadow/issues/12
238 #'paper-shadow',
239 'paper-tabs',
240 'paper-toggle-button',
242 for p in TAPPABLE_PAGES:
243 self.AddStory(PolymerSampler(
244 self, p, run_no_page_interactions=run_no_page_interactions))
246 # Polymer Sampler subpages that are interesting to scroll
247 SCROLLABLE_PAGES = [
248 'core-scroll-header-panel',
250 for p in SCROLLABLE_PAGES:
251 self.AddStory(PolymerSampler(
252 self, p, run_no_page_interactions=run_no_page_interactions,
253 scrolling_page=True))
255 for page in self:
256 assert (page.__class__.RunPageInteractions ==
257 PolymerPage.RunPageInteractions), (
258 'Pages in this page set must not override PolymerPage\' '
259 'RunPageInteractions method.')