# Copyright 2013 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 json import logging import os import time from distutils.version import LooseVersion from PIL import Image from ..common import cloud_bucket from ..common import ispy_utils class ChromeUtils(object): """A utility for using ISpy with Chrome.""" def __init__(self, cloud_bucket, version_file, screenshot_func): """Initializes the utility class. Args: cloud_bucket: a BaseCloudBucket in which to the version file, expectations and results are to be stored. version_file: path to the version file in the cloud bucket. The version file contains a json list of ordered Chrome versions for which expectations exist. screenshot_func: a function that returns a PIL.Image. """ self._cloud_bucket = cloud_bucket self._version_file = version_file self._screenshot_func = screenshot_func self._ispy = ispy_utils.ISpyUtils(self._cloud_bucket) with open( os.path.join(os.path.dirname(__file__), 'wait_on_ajax.js'), 'r') as f: self._wait_for_unchanging_dom_script = f.read() def UpdateExpectationVersion(self, chrome_version): """Updates the most recent expectation version to the Chrome version. Should be called after generating a new set of expectations. Args: chrome_version: the chrome version as a string of the form "31.0.123.4". """ insert_pos = 0 expectation_versions = [] try: expectation_versions = self._GetExpectationVersionList() if expectation_versions: try: version = self._GetExpectationVersion( chrome_version, expectation_versions) if version == chrome_version: return insert_pos = expectation_versions.index(version) except: insert_pos = len(expectation_versions) except cloud_bucket.FileNotFoundError: pass expectation_versions.insert(insert_pos, chrome_version) logging.info('Updating expectation version...') self._cloud_bucket.UploadFile( self._version_file, json.dumps(expectation_versions), 'application/json') def _GetExpectationVersion(self, chrome_version, expectation_versions): """Returns the expectation version for the given Chrome version. Args: chrome_version: the chrome version as a string of the form "31.0.123.4". expectation_versions: Ordered list of Chrome versions for which expectations exist, as stored in the version file. Returns: Expectation version string. """ # Find the closest version that is not greater than the chrome version. for version in expectation_versions: if LooseVersion(version) <= LooseVersion(chrome_version): return version raise Exception('No expectation exists for Chrome %s' % chrome_version) def _GetExpectationVersionList(self): """Gets the list of expectation versions from google storage.""" return json.loads(self._cloud_bucket.DownloadFile(self._version_file)) def _GetExpectationNameWithVersion(self, device_type, expectation, chrome_version): """Get the expectation to be used with the current Chrome version. Args: device_type: string identifier for the device type. expectation: name for the expectation to generate. chrome_version: the chrome version as a string of the form "31.0.123.4". Returns: Version as an integer. """ version = self._GetExpectationVersion( chrome_version, self._GetExpectationVersionList()) return self._CreateExpectationName(device_type, expectation, version) def _CreateExpectationName(self, device_type, expectation, version): """Create the full expectation name from the expectation and version. Args: device_type: string identifier for the device type, example: mako expectation: base name for the expectation, example: google.com version: expectation version, example: 31.0.23.1 Returns: Full expectation name as a string, example: mako:google.com(31.0.23.1) """ return '%s:%s(%s)' % (device_type, expectation, version) def GenerateExpectation(self, device_type, expectation, chrome_version): """Take screenshots and store as an expectation in I-Spy. Args: device_type: string identifier for the device type. expectation: name for the expectation to generate. chrome_version: the chrome version as a string of the form "31.0.123.4". """ # https://code.google.com/p/chromedriver/issues/detail?id=463 time.sleep(1) expectation_with_version = self._CreateExpectationName( device_type, expectation, chrome_version) if self._ispy.ExpectationExists(expectation_with_version): logging.warning( 'I-Spy expectation \'%s\' already exists, overwriting.', expectation_with_version) screenshots = [self._screenshot_func() for _ in range(8)] logging.info('Generating I-Spy expectation...') self._ispy.GenerateExpectation(expectation_with_version, screenshots) def PerformComparison(self, test_run, device_type, expectation, chrome_version): """Take a screenshot and compare it with the given expectation in I-Spy. Args: test_run: name for the test run. device_type: string identifier for the device type. expectation: name for the expectation to compare against. chrome_version: the chrome version as a string of the form "31.0.123.4". """ # https://code.google.com/p/chromedriver/issues/detail?id=463 time.sleep(1) screenshot = self._screenshot_func() logging.info('Performing I-Spy comparison...') self._ispy.PerformComparison( test_run, self._GetExpectationNameWithVersion( device_type, expectation, chrome_version), screenshot) def GetScriptToWaitForUnchangingDOM(self): """Returns a JavaScript script that waits for the DOM to stop changing.""" return self._wait_for_unchanging_dom_script