OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2016 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 | |
5 import sys | |
6 | |
7 from page_sets.system_health import platforms | |
8 from page_sets.system_health import system_health_story | |
9 | |
10 from telemetry import story | |
11 | |
12 | |
13 class _BrowsingStory(system_health_story.SystemHealthStory): | |
14 """Abstract base class for browsing stories. | |
15 | |
16 A browsing story visits items on the main page. Subclasses provide | |
17 CSS selector to identify the items and implement interaction using | |
18 the helper methods of this class. | |
19 """ | |
20 | |
21 IS_SINGLE_PAGE_APP = False | |
22 ITEM_SELECTOR = NotImplemented | |
23 ITEMS_TO_VISIT = 4 | |
24 | |
25 def __init__(self, story_set): | |
26 super(_BrowsingStory, self).__init__( | |
27 story_set, take_memory_measurement=False) | |
28 | |
29 def _Item(self, index): | |
petrcermak
2016/07/08 12:46:03
nit: I think that this should be called something
ulan
2016/07/08 13:57:56
I inlined this function in NavigateToItem.
| |
30 return 'document.querySelectorAll(\'%s\')[%d]' % ( | |
petrcermak
2016/07/08 12:46:03
nit: I suggest you use " inside the string to avoi
ulan
2016/07/08 13:57:56
Done.
| |
31 self.ITEM_SELECTOR, index) | |
32 | |
33 def _WaitForItem(self, action_runner, index): | |
petrcermak
2016/07/08 12:46:03
Do you expect any subclass to override _WaitForIte
ulan
2016/07/08 13:57:57
Done. I thought that the media browsing benchmark
| |
34 action_runner.WaitForElement(element_function=self._Item(index)) | |
35 | |
36 def _ClickItem(self, action_runner, index): | |
37 action_runner.ClickElement(element_function=self._Item(index)) | |
38 | |
39 def _WaitForNavigation(self, action_runner): | |
40 if not self.IS_SINGLE_PAGE_APP: | |
41 action_runner.WaitForNavigate() | |
42 | |
43 def _NavigateBack(self, action_runner): | |
44 action_runner.ExecuteJavaScript('window.history.back()') | |
45 self._WaitForNavigation(action_runner) | |
46 | |
47 | |
48 class _NewsBrowsingStory(_BrowsingStory): | |
49 """Abstract base class for news user stories. | |
50 | |
51 A news story imitates browsing a news website: | |
52 1. Load the main page. | |
53 2. Open and scroll the first news item. | |
54 3. Go back to the main page and scroll it. | |
55 4. Open and scroll the second news item. | |
56 5. Go back to the main page and scroll it. | |
57 6. etc. | |
58 """ | |
59 | |
60 ITEM_READ_TIME_IN_SECONDS = 3 | |
61 ITEM_SCROLL_REPEAT = 2 | |
62 MAIN_PAGE_SCROLL_REPEAT = 0 | |
63 | |
64 def RunPageInteractions(self, action_runner): | |
ulan
2016/07/08 10:50:55
This one is not calling the SystemHealthStory.RunP
petrcermak
2016/07/08 12:46:03
I think that the best solution would be to move th
ulan
2016/07/08 13:57:57
I am using _DidLoadDocument as a hook to do specia
petrcermak
2016/07/08 15:06:28
I don't think that's true. You get action_runner.t
ulan
2016/07/08 15:40:47
Very nice, thank you! I didn't think about that. D
| |
65 action_runner.tab.WaitForDocumentReadyStateToBeComplete() | |
66 self._DidLoadDocument(action_runner) | |
67 for i in xrange(self.ITEMS_TO_VISIT): | |
68 self._NavigateToNewsItem(action_runner, i) | |
69 self._ReadNewsItem(action_runner) | |
70 self._NavigateBack(action_runner) | |
71 self._ScrollMainPage(action_runner) | |
72 | |
73 def _NavigateToNewsItem(self, action_runner, index): | |
petrcermak
2016/07/08 12:46:03
Why is this method not defined on _BrowsingStory?
ulan
2016/07/08 13:57:57
Done.
| |
74 self._WaitForItem(action_runner, index) | |
petrcermak
2016/07/08 12:46:03
These methods build the item selector twice unnece
ulan
2016/07/08 13:57:56
Done, but I left WaitForNavigation in separate fun
petrcermak
2016/07/12 12:53:19
Acknowledged.
| |
75 self._ClickItem(action_runner, index) | |
76 self._WaitForNavigation(action_runner) | |
77 | |
78 def _ReadNewsItem(self, action_runner): | |
79 action_runner.tab.WaitForDocumentReadyStateToBeComplete() | |
80 action_runner.Wait(self.ITEM_READ_TIME_IN_SECONDS) | |
81 action_runner.RepeatableBrowserDrivenScroll( | |
82 repeat_count=self.ITEM_SCROLL_REPEAT) | |
83 | |
84 def _ScrollMainPage(self, action_runner): | |
85 action_runner.tab.WaitForDocumentReadyStateToBeComplete() | |
86 action_runner.RepeatableBrowserDrivenScroll( | |
87 repeat_count=self.MAIN_PAGE_SCROLL_REPEAT) | |
88 | |
89 | |
90 ############################################################################## | |
91 # News browsing stories. | |
92 ############################################################################## | |
93 | |
nednguyen
2016/07/08 12:54:42
Looks like we don't cover any non-US news pages he
Hannes Payer (out of office)
2016/07/08 13:52:54
Hacker news is nice because it goes to other webpa
ulan
2016/07/08 13:57:57
Petr suggested to sync load:news and browse:news.
nednguyen
2016/07/08 14:01:35
Ah, that's a good point. Those I think we should u
nednguyen
2016/07/08 14:17:14
Keeping reddit is fine.
I suggest we replace hacke
petrcermak
2016/07/08 15:06:29
Facebook and Twitter are in load:social. I suggest
ulan
2016/07/08 15:40:47
Changed facebook and twitter to browse:social.
I'
petrcermak
2016/07/08 15:58:39
SGTM. Thanks :-)
| |
94 | |
95 class RedditDesktopStory(_NewsBrowsingStory): | |
96 """The top website in http://www.alexa.com/topsites/category/News""" | |
97 NAME = 'browse:news:reddit' | |
98 URL = 'https://www.reddit.com/top/?sort=top&t=week' | |
99 SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY | |
100 ITEM_SELECTOR = '.thing .title > a' | |
101 | |
102 | |
103 class RedditMobileStory(_NewsBrowsingStory): | |
104 """The top website in http://www.alexa.com/topsites/category/News""" | |
105 NAME = 'browse:news:reddit' | |
106 URL = 'https://m.reddit.com/?sort=top&time=week' | |
107 SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY | |
108 ITEM_SELECTOR = '.PostHeader__post-title-line' | |
109 IS_SINGLE_PAGE_APP = True | |
110 | |
111 | |
112 class CnnStory(_NewsBrowsingStory): | |
113 """The second top website in http://www.alexa.com/topsites/category/News""" | |
114 NAME = 'browse:news:cnn' | |
115 URL = 'http://edition.cnn.com/' | |
116 ITEM_SELECTOR = '.cd__content > h3 > a' | |
117 # TODO(ulan): Enable this story on mobile once it uses less memory and | |
118 # does not crash with OOM. | |
119 SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY | |
120 | |
121 | |
122 class NytimesMobileStory(_NewsBrowsingStory): | |
123 """The third top website in http://www.alexa.com/topsites/category/News""" | |
124 NAME = 'browse:news:nytimes' | |
125 URL = 'http://mobile.nytimes.com' | |
126 SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY | |
127 ITEM_SELECTOR = '.sfgAsset-link' | |
128 # Visiting more items causes OOM. | |
129 ITEMS_TO_VISIT = 2 | |
130 | |
131 | |
132 class NytimesDesktopStory(_NewsBrowsingStory): | |
133 """The third top website in http://www.alexa.com/topsites/category/News""" | |
134 NAME = 'browse:news:nytimes' | |
135 URL = 'http://www.nytimes.com' | |
136 SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY | |
137 ITEM_SELECTOR = '.story-heading > a' | |
138 | |
139 | |
140 class HackerNewsStory(_NewsBrowsingStory): | |
141 NAME = 'browse:news:hackernews' | |
142 URL = 'https://news.ycombinator.com' | |
143 ITEM_SELECTOR = '.athing .title > a' | |
144 | |
145 | |
146 # Facebook on desktop is not interesting because it embeds post comments | |
147 # directly in the main timeline. | |
148 class FacebookMobileStory(_NewsBrowsingStory): | |
149 NAME = 'browse:news:facebook' | |
150 URL = 'https://facebook.com/natgeo' | |
151 ITEM_SELECTOR = 'article ._5msj' | |
152 SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY | |
153 | |
154 | |
155 class TwitterMobileStory(_NewsBrowsingStory): | |
156 NAME = 'browse:news:twitter' | |
157 URL = 'https://mobile.twitter.com/cnnbrk' | |
158 ITEM_SELECTOR = '.Tweet-text' | |
159 SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY | |
160 | |
161 | |
162 class TwitterDesktopStory(_NewsBrowsingStory): | |
163 NAME = 'browse:news:twitter' | |
164 URL = 'https://twitter.com/cnnbrk' | |
165 ITEM_SELECTOR = '.tweet-text' | |
166 SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY | |
167 IS_SINGLE_PAGE_APP = True | |
168 | |
169 | |
170 class WashingtonPostMobileStory(_NewsBrowsingStory): | |
171 """Progressive website""" | |
172 NAME = 'browse:news:washingtonpost' | |
173 URL = 'https://www.washingtonpost.com/pwa' | |
174 SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY | |
175 ITEM_SELECTOR = '.hed > a' | |
176 IS_SINGLE_PAGE_APP = True | |
177 | |
178 def _DidLoadDocument(self, action_runner): | |
179 # Close the popup window. | |
180 action_runner.ClickElement(selector='.close') | |
181 | |
182 | |
183 class WashingtonPostDesktopStory(_NewsBrowsingStory): | |
184 NAME = 'browse:news:washingtonpost' | |
185 URL = 'https://www.washingtonpost.com' | |
186 SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY | |
187 ITEM_SELECTOR = '.headline > a' | |
188 | |
189 | |
190 ############################################################################## | |
191 # Browsing story sets. | |
192 ############################################################################## | |
193 | |
petrcermak
2016/07/08 12:46:03
nit: please add a second blank line here (there sh
ulan
2016/07/08 13:57:57
Done.
| |
194 def IterAllStoryClasses(): | |
petrcermak
2016/07/08 12:46:03
This will also return the _NewsBrowsingStory abstr
ulan
2016/07/08 13:57:57
Done.
| |
195 return system_health_story.IterAllStoryClasses( | |
196 sys.modules[__name__], _BrowsingStory) | |
197 | |
198 | |
199 def IterAllNewsBrowsingStoryClasses(): | |
petrcermak
2016/07/08 12:46:03
I'd make this private for the time being (leading
ulan
2016/07/08 13:57:56
Done.
| |
200 return system_health_story.IterAllStoryClasses( | |
201 sys.modules[__name__], _NewsBrowsingStory) | |
202 | |
203 | |
204 class _NewsBrowsingStorySet(story.StorySet): | |
205 PLATFORM = NotImplemented | |
206 | |
207 def __init__(self): | |
208 super(_NewsBrowsingStorySet, self).__init__( | |
209 archive_data_file=('../data/news_%s.json' % self.PLATFORM), | |
210 cloud_storage_bucket=story.PARTNER_BUCKET) | |
211 for story_class in IterAllNewsBrowsingStoryClasses(): | |
212 if self.PLATFORM not in story_class.SUPPORTED_PLATFORMS: | |
213 continue | |
214 self.AddStory(story_class(self)) | |
215 | |
216 | |
217 class DesktopNewsStorySet(_NewsBrowsingStorySet): | |
218 PLATFORM = platforms.DESKTOP | |
219 | |
220 | |
221 class MobileNewsStorySet(_NewsBrowsingStorySet): | |
222 PLATFORM = platforms.MOBILE | |
OLD | NEW |