Chromium Code Reviews| 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 telemetry.page import page | |
| 8 | |
| 9 from telemetry.core import discover | |
| 10 from telemetry import story | |
| 11 | |
| 12 _ALL_PLATFORMS = frozenset({'desktop', 'mobile'}) | |
| 13 _DESKTOP_ONLY = frozenset({'desktop'}) | |
| 14 _MOBILE_ONLY = frozenset({'mobile'}) | |
| 15 _NO_PLATFORMS = frozenset() | |
| 16 _NEWS_ITEM_READ_TIME_IN_SECONDS = 3 | |
| 17 | |
| 18 class _NewsStory(page.Page): | |
|
petrcermak
2016/07/07 14:55:56
I can see that this class is modelled very closely
ulan
2016/07/07 17:34:38
Sounds good. I will do this change tomorrow.
| |
| 19 """Abstract base class for news user stories. | |
| 20 | |
| 21 A news story imitates browsing a news website: | |
| 22 1. Load the main page. | |
| 23 2. Open and scroll the first news item. | |
| 24 3. Go back to the main page and scroll it. | |
| 25 4. Open and scroll the second news item. | |
| 26 5. Go back to the main page and scroll it. | |
| 27 6. etc. | |
| 28 """ | |
| 29 | |
| 30 NAME = NotImplemented | |
| 31 URL = NotImplemented | |
| 32 NEWS_ITEM_SELECTOR = NotImplemented | |
| 33 NEWS_ITEMS_TO_VISIT = 4 | |
| 34 SUPPORTED_PLATFORMS = _ALL_PLATFORMS | |
| 35 IS_SINGLE_PAGE_APP = False | |
| 36 | |
| 37 def __init__(self, story_set): | |
| 38 super(_NewsStory, self).__init__( | |
| 39 page_set=story_set, name=self.NAME, url=self.URL) | |
| 40 | |
| 41 def RunPageInteractions(self, action_runner): | |
| 42 action_runner.tab.WaitForDocumentReadyStateToBeComplete() | |
| 43 self._DidLoadDocument(action_runner) | |
| 44 for i in xrange(self.NEWS_ITEMS_TO_VISIT): | |
| 45 self._ClickNewsItem(action_runner, i) | |
| 46 self._ReadNewsItem(action_runner) | |
| 47 self._NavigateBack(action_runner) | |
| 48 self._ScrollMainPage(action_runner) | |
| 49 | |
| 50 def _NewsItem(self, index): | |
| 51 return 'document.querySelectorAll(\'%s\')[%d]' % ( | |
| 52 self.NEWS_ITEM_SELECTOR, index) | |
| 53 | |
| 54 def _DidLoadDocument(self, action_runner): | |
| 55 pass | |
| 56 | |
| 57 def _WaitForNavigation(self, action_runner): | |
| 58 if not self.IS_SINGLE_PAGE_APP: | |
| 59 action_runner.WaitForNavigate() | |
| 60 | |
| 61 def _ClickNewsItem(self, action_runner, index): | |
| 62 action_runner.WaitForElement(element_function=self._NewsItem(index)) | |
| 63 action_runner.ClickElement(element_function=self._NewsItem(index)) | |
| 64 self._WaitForNavigation(action_runner) | |
| 65 | |
| 66 def _ReadNewsItem(self, action_runner): | |
| 67 action_runner.tab.WaitForDocumentReadyStateToBeComplete() | |
| 68 action_runner.Wait(_NEWS_ITEM_READ_TIME_IN_SECONDS) | |
| 69 action_runner.RepeatableBrowserDrivenScroll(repeat_count=2) | |
| 70 | |
| 71 def _NavigateBack(self, action_runner): | |
| 72 action_runner.ExecuteJavaScript('window.history.back()') | |
| 73 self._WaitForNavigation(action_runner) | |
| 74 | |
| 75 def _ScrollMainPage(self, action_runner): | |
| 76 action_runner.tab.WaitForDocumentReadyStateToBeComplete() | |
| 77 action_runner.RepeatableBrowserDrivenScroll(repeat_count=0) | |
| 78 | |
| 79 | |
| 80 def IterAllStoryClasses(): | |
| 81 # Sort the classes by their names so that their order is stable and | |
| 82 # deterministic. | |
| 83 for unused_cls_name, cls in sorted(discover.DiscoverClassesInModule( | |
| 84 module=sys.modules[__name__], | |
| 85 base_class=_NewsStory, | |
| 86 index_by_class_name=True).iteritems()): | |
| 87 yield cls | |
| 88 | |
| 89 | |
| 90 ############################################################################## | |
| 91 # News stories. | |
| 92 ############################################################################## | |
| 93 | |
| 94 | |
| 95 class RedditDesktopStory(_NewsStory): | |
| 96 """The top website in http://www.alexa.com/topsites/category/News""" | |
| 97 NAME = 'reddit' | |
| 98 URL = 'https://www.reddit.com/top/?sort=top&t=week' | |
| 99 SUPPORTED_PLATFORMS = _DESKTOP_ONLY | |
| 100 NEWS_ITEM_SELECTOR = '.thing .title > a' | |
| 101 | |
| 102 | |
| 103 class RedditMobileStory(_NewsStory): | |
| 104 """The top website in http://www.alexa.com/topsites/category/News""" | |
| 105 NAME = 'reddit' | |
| 106 URL = 'https://m.reddit.com/?sort=top&time=week' | |
| 107 SUPPORTED_PLATFORMS = _MOBILE_ONLY | |
| 108 NEWS_ITEM_SELECTOR = '.PostHeader__post-title-line' | |
| 109 IS_SINGLE_PAGE_APP = True | |
| 110 | |
| 111 | |
| 112 class CnnStory(_NewsStory): | |
| 113 """The second top website in http://www.alexa.com/topsites/category/News""" | |
| 114 NAME = 'cnn' | |
| 115 URL = 'http://edition.cnn.com/' | |
| 116 NEWS_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 = _DESKTOP_ONLY | |
| 120 | |
| 121 | |
| 122 class NytimesMobileStory(_NewsStory): | |
| 123 """The third top website in http://www.alexa.com/topsites/category/News""" | |
| 124 NAME = 'nytimes' | |
| 125 URL = 'http://mobile.nytimes.com' | |
| 126 SUPPORTED_PLATFORMS = _MOBILE_ONLY | |
| 127 NEWS_ITEM_SELECTOR = '.sfgAsset-link' | |
| 128 # Visiting more items causes OOM. | |
| 129 NEWS_ITEMS_TO_VISIT = 2 | |
| 130 | |
| 131 | |
| 132 class NytimesDesktopStory(_NewsStory): | |
| 133 """The third top website in http://www.alexa.com/topsites/category/News""" | |
| 134 NAME = 'nytimes' | |
| 135 URL = 'http://www.nytimes.com' | |
| 136 SUPPORTED_PLATFORMS = _DESKTOP_ONLY | |
| 137 NEWS_ITEM_SELECTOR = '.story-heading > a' | |
| 138 | |
| 139 | |
| 140 class HackerNewsStory(_NewsStory): | |
| 141 NAME = 'hackernews' | |
| 142 URL = 'https://news.ycombinator.com' | |
| 143 NEWS_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(_NewsStory): | |
| 149 NAME = 'facebook' | |
| 150 URL = 'https://facebook.com/natgeo' | |
| 151 NEWS_ITEM_SELECTOR = 'article ._5msj' | |
| 152 SUPPORTED_PLATFORMS = _MOBILE_ONLY | |
| 153 | |
| 154 | |
| 155 class TwitterMobileStory(_NewsStory): | |
| 156 NAME = 'twitter' | |
| 157 URL = 'https://mobile.twitter.com/cnnbrk' | |
| 158 NEWS_ITEM_SELECTOR = '.Tweet-text' | |
| 159 SUPPORTED_PLATFORMS = _MOBILE_ONLY | |
| 160 | |
| 161 | |
| 162 class TwitterDesktopStory(_NewsStory): | |
| 163 NAME = 'twitter' | |
| 164 URL = 'https://twitter.com/cnnbrk' | |
| 165 NEWS_ITEM_SELECTOR = '.tweet-text' | |
| 166 SUPPORTED_PLATFORMS = _DESKTOP_ONLY | |
| 167 IS_SINGLE_PAGE_APP = True | |
| 168 | |
| 169 | |
| 170 class WashingtonPostMobileStory(_NewsStory): | |
| 171 """Progressive website""" | |
| 172 NAME = 'washingtonpost' | |
| 173 URL = 'https://www.washingtonpost.com/pwa' | |
| 174 SUPPORTED_PLATFORMS = _MOBILE_ONLY | |
| 175 NEWS_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(_NewsStory): | |
| 184 NAME = 'washingtonpost' | |
| 185 URL = 'https://www.washingtonpost.com' | |
| 186 SUPPORTED_PLATFORMS = _DESKTOP_ONLY | |
| 187 NEWS_ITEM_SELECTOR = '.headline > a' | |
| 188 | |
| 189 | |
| 190 ############################################################################## | |
| 191 # News story sets. | |
| 192 ############################################################################## | |
| 193 | |
| 194 | |
| 195 class _NewsStorySet(story.StorySet): | |
| 196 PLATFORM = NotImplemented | |
| 197 | |
| 198 def __init__(self): | |
| 199 super(_NewsStorySet, self).__init__( | |
| 200 archive_data_file=('../data/news_%s.json' % self.PLATFORM), | |
| 201 cloud_storage_bucket=story.PARTNER_BUCKET) | |
| 202 for story_class in IterAllStoryClasses(): | |
| 203 if self.PLATFORM not in story_class.SUPPORTED_PLATFORMS: | |
| 204 continue | |
| 205 self.AddStory(story_class(self)) | |
| 206 | |
| 207 | |
| 208 class DesktopNewsStorySet(_NewsStorySet): | |
| 209 PLATFORM = 'desktop' | |
| 210 | |
| 211 | |
| 212 class MobileNewsStorySet(_NewsStorySet): | |
| 213 PLATFORM = 'mobile' | |
| OLD | NEW |