Home | History | Annotate | Download | only in gtalk
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 """Basic sanity tests for the GTalk extension.
      7 
      8 This module contains the basic set of sanity tests run on the
      9 GTalk extension.
     10 """
     11 
     12 import logging
     13 import sys
     14 import time
     15 import traceback
     16 import urllib2
     17 import os
     18 
     19 import gtalk_base_test
     20 import pyauto_gtalk  # must preceed pyauto
     21 import pyauto
     22 
     23 
     24 class BasicTest(gtalk_base_test.GTalkBaseTest):
     25   """Test for Google Talk Chrome Extension."""
     26 
     27   def _OpenRoster(self, gtalk_version):
     28     """Download Talk extension and open the roster."""
     29 
     30     self.InstallGTalkExtension(gtalk_version)
     31 
     32     # Wait for the background view to load.
     33     extension = self.GetGTalkExtensionInfo()
     34     background_view = self.WaitUntilExtensionViewLoaded(
     35         extension_id=extension['id'],
     36         view_type='EXTENSION_BACKGROUND_PAGE')
     37     self.assertTrue(background_view,
     38         msg='Failed to get background view: views = %s.' %
     39         self.GetBrowserInfo()['extension_views'])
     40 
     41     # Click browser action icon
     42     self.TriggerBrowserActionById(extension['id'])
     43 
     44     # Wait for viewer window to open.
     45     self.assertTrue(
     46         self.WaitUntil(self.GetViewerInfo),
     47         msg='Timed out waiting for viewer.html to open.')
     48 
     49     # Wait for the sign-in iframe to load.
     50     self.WaitUntilCondition(
     51         lambda: self.RunInViewer(
     52             'window.document.getElementsByTagName("iframe") != null && '
     53             'window.document.getElementsByTagName("iframe").length > 0') and
     54             self.RunInViewer('window.location.href',
     55                              '//iframe[1]'),
     56         lambda url: url and '/qsignin' in url,
     57         msg='Timed out waiting for /qsignin page.')
     58 
     59 
     60   def _SignIn(self, gtalk_version):
     61     """Download the extension, open the roster, and sign in"""
     62     # Open the roster.
     63     self._OpenRoster(gtalk_version)
     64 
     65     # Wait for /qsignin's BODY.
     66     self.WaitUntilResult(True,
     67         lambda: self.RunInViewer(
     68             'Boolean($BODY())', '//iframe[1]'),
     69         msg='Timed out waiting for document.body in /qsignin page.')
     70 
     71     # Wait for the "Sign In" link.
     72     self.WaitUntilResult(True,
     73         lambda: self.RunInViewer(
     74             'Boolean($FindByText($BODY(), "Sign In"))', '//iframe[1]'),
     75         msg='Timed out waiting for "Sign In" link in DOM.')
     76 
     77     # Click the "Sign In" link.
     78     self.assertTrue(self.RunInViewer(
     79         '$Click($FindByText($BODY(), "Sign In"))', '//iframe[1]'))
     80 
     81     # Wait for the login page to open.
     82     self.assertTrue(self.WaitUntil(self.GetLoginPageInfo),
     83         msg='Timed out waiting for login page to open.')
     84 
     85     # Wait for the login page's form element.
     86     self.WaitUntilResult(True,
     87         lambda: self.RunInLoginPage('Boolean(document.forms[0])'),
     88         msg='Timed out waiting for document.forms[0].')
     89 
     90     # Fill and submit the login form.
     91     credentials = self.GetPrivateInfo()['test_google_account']
     92 
     93     self.RunInLoginPage(
     94         'document.forms[0].Email.value="' + credentials['username'] + '"')
     95     self.RunInLoginPage(
     96         'document.forms[0].Passwd.value="' + credentials['password'] + '"')
     97     self.RunInLoginPage('document.forms[0].submit() || true')
     98 
     99   def RunBasicFunctionalityTest(self, gtalk_version):
    100     """Run tests for basic functionality in GTalk."""
    101 
    102     # Install the extension, open the viewer, and sign in.
    103     self._SignIn(gtalk_version)
    104 
    105     # Wait for the roster container iframe.
    106     self.WaitUntilResult(True,
    107         lambda: self.RunInViewer(
    108         'window.document.getElementById("popoutRoster") != null'),
    109         msg='Timed out waiting for roster container iframe.')
    110 
    111     self.WaitUntilResult(True,
    112         lambda: self.RunInViewer('Boolean(window.frames[0])', '//iframe[1]'),
    113         msg='Timed out waiting for roster iframe.')
    114 
    115     # Wait for the roster iframe to load.
    116     self.WaitUntilCondition(
    117         lambda: self.RunInRoster('window.location.href'),
    118         lambda url: url and '/frame' in url,
    119         msg='Timed out waiting for /frame in url.')
    120 
    121     self.WaitUntilResult(True,
    122         lambda: self.RunInRoster(
    123         'Boolean($FindByText($BODY(), "Send a message to..."))'),
    124         msg='Timed out waiting for "Send a message to..." label in roster DOM.')
    125 
    126     # Wait for "chatpinger (at] appspot.com" to appear in the roster.
    127     self.WaitUntilResult(True,
    128         lambda: self.RunInRoster(
    129             'Boolean($FindByText($BODY(), "chatpinger (at] appspot.com"))'),
    130         msg='Timed out waiting for chatpinger (at] appspot.com in roster DOM.')
    131 
    132     # Works around for issue where mole doesn't open when clicked too quickly.
    133     time.sleep(1)
    134 
    135     # Click "chatpinger (at] appspot.com" to open a chat mole.
    136     self.RunInRoster('$Click($FindByText($BODY(), "chatpinger (at] appspot.com"))')
    137 
    138     # Wait until ready to check whether mole is open(temporary work around).
    139     time.sleep(1)
    140 
    141     # Wait for chat mole to open.
    142     self.assertTrue(self.WaitUntil(self.GetMoleInfo),
    143         msg='Timed out waiting for mole window to open.')
    144 
    145     self.WaitUntilResult(True,
    146         lambda: self.RunInViewer(
    147         'window.document.getElementsByTagName("iframe") != null'),
    148         msg='Timed out waiting for iframes to load.')
    149 
    150     # Wait for chat mole to load.
    151     self.WaitUntilResult(True,
    152         lambda: self.RunInMole('Boolean(window.location.href)'),
    153         msg='Timed out waiting for mole window location.')
    154 
    155     # Wait for the chat mole's input textarea to load.
    156     self.WaitUntilResult(True,
    157         lambda: self.RunInMole(
    158             'Boolean($FindByTagName($BODY(), "textarea", 0))'),
    159         msg='Timed out waiting for mole textarea.')
    160 
    161     # Type /ping in the mole's input widget.
    162     self.assertTrue(self.RunInMole(
    163         '$Type($FindByTagName($BODY(), "textarea", 0), "/ping")'),
    164         msg='Error typing in mole textarea.')
    165 
    166     # Type ENTER in the mole's input widget.
    167     self.assertTrue(self.RunInMole(
    168         '$Press($FindByTagName($BODY(),"textarea",0), $KEYS.ENTER)'),
    169         msg='Error sending ENTER in mole textarea.')
    170 
    171     # Wait for chat input to clear.
    172     self.WaitUntilResult(True,
    173         lambda: self.RunInMole(
    174             'Boolean($FindByTagName($BODY(),"textarea",0).value=="")'),
    175         msg='Timed out waiting for textarea to clear after ENTER.')
    176 
    177     # Wait for /ping to appear in the chat history.
    178     self.WaitUntilCondition(
    179         lambda: self.RunInMole('window.document.body.innerHTML'),
    180         lambda html: html and '/ping' in html,
    181         msg='Timed out waiting for /ping to appear in mole DOM.')
    182 
    183     # Wait for the echo "Ping!" to appear in the chat history.
    184     self.WaitUntilCondition(
    185         lambda: self.RunInMole('window.document.body.innerHTML'),
    186         lambda html: html and 'Ping!' in html,
    187         msg='Timed out waiting for "Ping!" reply to appear in mole DOM.')
    188 
    189     # Request a ping in 7 seconds.
    190     self.assertTrue(self.RunInMole(
    191         '$Type($FindByTagName($BODY(),"textarea",0), "/ping 7")'),
    192         msg='Error typing "ping /7" in mole textarea.')
    193 
    194     # Press Enter in chat input.
    195     self.assertTrue(self.RunInMole(
    196         '$Press($FindByTagName($BODY(),"textarea",0), $KEYS.ENTER)'),
    197         msg='Error sending ENTER after "ping /7" in mole textarea.')
    198 
    199     # Briefly show mole for visual examination.
    200     # Also works around issue where extension may show the first
    201     # Ping! notification before closing the mole.
    202     time.sleep(2)
    203 
    204     # Press escape to close the mole.
    205     self.assertTrue(self.RunInMole(
    206         '$Press($FindByTagName($BODY(),"textarea",0), $KEYS.ESC)'),
    207         msg='Error sending ESC after "ping /7" in mole textarea.')
    208 
    209     # Wait for the mole to close.
    210     self.assertTrue(self.WaitUntil(
    211         lambda: not(bool(self.GetMoleInfo()))),
    212         msg='Timed out waiting for chatpinger mole to close.')
    213 
    214     # Ensure "chatpinger2 (at] appspot.com" is in the roster.
    215     self.WaitUntilResult(True,
    216         lambda: self.RunInRoster(
    217             'Boolean($FindByText($BODY(), "chatpinger2 (at] appspot.com"))'),
    218         msg='Timed out waiting for chatpinger2 (at] appspot.com in roster DOM.')
    219 
    220     # Click "chatpinger2 (at] appspot.com" in the roster.
    221     self.RunInRoster('$Click($FindByText($BODY(), "chatpinger2 (at] appspot.com"))')
    222 
    223     self.WaitUntilResult(True,
    224         lambda: self.RunInViewer(
    225         'window.document.getElementsByTagName("iframe") != null'),
    226         msg='Timed out waiting for iframes to load.')
    227 
    228     # Wait for a second chat mole to open.
    229     time.sleep(1)
    230     self.assertTrue(self.WaitUntil(lambda: bool(self.GetMoleInfo(1))),
    231         msg='Timed out waiting for second mole window to open.')
    232 
    233     # Wait for mole content to load
    234     self.WaitUntilCondition(
    235         lambda: self.RunInMole('window.document.body.innerHTML', 1),
    236         lambda html: html and 'Ping!' in html,
    237         msg='Timed out waiting for Ping! to appear in mole DOM.')
    238 
    239     # Disable the extension.
    240     extension = self.GetGTalkExtensionInfo()
    241     self.SetExtensionStateById(extension['id'], enable=False,
    242         allow_in_incognito=False)
    243     extension = self.GetGTalkExtensionInfo()
    244     self.assertFalse(extension['is_enabled'])
    245 
    246     # Verify all moles + windows are closed.
    247     self.assertTrue(self.WaitUntil(lambda: not(bool(self.GetViewerInfo()))),
    248         msg='Timed out waiting for viewer.html to close after disabling.')
    249     self.assertTrue(self.WaitUntil(lambda: not(bool(self.GetMoleInfo()))),
    250         msg='Timed out waiting for first mole to close after disabling.')
    251     self.assertTrue(self.WaitUntil(lambda: not(bool(self.GetMoleInfo(1)))),
    252         msg='Timed out waiting for second mole to close after disabling.')
    253 
    254   def _GetCurrentGtalkVersion(self):
    255     """Read current gtalk extension version from file."""
    256     return self._GetGtalkVersion('current_version')
    257 
    258   def _GetRCGtalkVersion(self):
    259     """Read RC gtalk extension version from file"""
    260     return self._GetGtalkVersion('rc_version')
    261 
    262   def _GetGtalkVersion(self, version_type):
    263     """Read gtalk version from file"""
    264     version_path = os.path.abspath(
    265         os.path.join(self.DataDir(), 'extensions',
    266                      'gtalk', version_type))
    267     self.assertTrue(
    268         os.path.exists(version_path),
    269         msg='Failed to find version ' + version_path)
    270     with open(version_path) as version_file:
    271       return version_file.read()
    272 
    273   def _TestBasicFunctionality(self, version):
    274     """Run tests for basic functionality in GTalk with retries."""
    275 
    276     # Since this test goes against prod servers, we'll retry to mitigate
    277     # flakiness due to network issues.
    278     RETRIES = 5
    279     for tries in range(RETRIES):
    280       logging.info('Calling RunBasicFunctionalityTest on %s. Try #%s/%s'
    281           % (version, tries + 1, RETRIES))
    282       try:
    283         self.RunBasicFunctionalityTest(version)
    284         logging.info('RunBasicFunctionalityTest on %s succeeded. Tries: %s'
    285             % (version, tries + 1))
    286         break
    287       except Exception as e:
    288         logging.info("\n*** ERROR in RunBasicFunctionalityTest ***")
    289         exc_type, exc_value, exc_traceback = sys.exc_info()
    290         traceback.print_exception(exc_type, exc_value, exc_traceback)
    291         logging.info("\n")
    292         if tries < RETRIES - 1:
    293           self.NavigateToURL('http://accounts.google.com/Logout')
    294           logging.info('Closing all moles.')
    295           self.RunInAllMoles(
    296               '$Press($FindByTagName($BODY(),"textarea",0), $KEYS.ESC)')
    297           logging.info('Retrying...')
    298         else:
    299           raise
    300 
    301   def testCurrentVersion(self):
    302     """Run basic functionality test on current version of gtalk extension"""
    303     version = self._GetCurrentGtalkVersion()
    304     self._TestBasicFunctionality(version)
    305 
    306   def testRCVersion(self):
    307     """Run basic functionality test on RC version of gtalk extension"""
    308     version = self._GetRCGtalkVersion()
    309     self._TestBasicFunctionality(version)
    310 
    311 if __name__ == '__main__':
    312   pyauto_gtalk.Main()
    313