xref: /aosp_15_r20/external/autotest/client/cros/semiauto_framework.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
3*9c5db199SXin Li# found in the LICENSE file.
4*9c5db199SXin Li
5*9c5db199SXin Liimport cgi, os
6*9c5db199SXin Li
7*9c5db199SXin Lifrom autotest_lib.client.bin import test
8*9c5db199SXin Lifrom autotest_lib.client.bin import utils
9*9c5db199SXin Lifrom autotest_lib.client.common_lib.cros import chrome
10*9c5db199SXin Li
11*9c5db199SXin Li_DEFAULT_TIMEOUT = 60  # Seconds a tester has to respond to prompts
12*9c5db199SXin Li
13*9c5db199SXin Li
14*9c5db199SXin Liclass semiauto_test(test.test):
15*9c5db199SXin Li    """Base class for semiauto tests in ChromeOS.
16*9c5db199SXin Li
17*9c5db199SXin Li    All these tests use telemetry and a simple interative webpage that
18*9c5db199SXin Li    navigates the user through the test.
19*9c5db199SXin Li    """
20*9c5db199SXin Li    version = 1
21*9c5db199SXin Li
22*9c5db199SXin Li    def login_and_open_interactive_tab(self):
23*9c5db199SXin Li        """Log in to machine, open browser, and navigate to dialog template.
24*9c5db199SXin Li
25*9c5db199SXin Li        Dialog template is on first tab.  Any other needed tabs can be opened
26*9c5db199SXin Li        using the self._browser object.
27*9c5db199SXin Li        """
28*9c5db199SXin Li        self._browser = chrome.Chrome(init_network_controller=True).browser
29*9c5db199SXin Li        self._tab = self._browser.tabs[0]
30*9c5db199SXin Li        self._browser.platform.SetHTTPServerDirectories(
31*9c5db199SXin Li                os.path.join(self.bindir, '..', '..', 'cros'))
32*9c5db199SXin Li        self._tab.Navigate(self._browser.platform.http_server.UrlOf(
33*9c5db199SXin Li                '/semiauto_shell.html'))
34*9c5db199SXin Li
35*9c5db199SXin Li    def close_browser(self):
36*9c5db199SXin Li        """Close browser if open."""
37*9c5db199SXin Li        if self._browser:
38*9c5db199SXin Li            self._browser.Close()
39*9c5db199SXin Li
40*9c5db199SXin Li    def set_tab(self, html):
41*9c5db199SXin Li        """Replace the body of self._tab with provided html.
42*9c5db199SXin Li
43*9c5db199SXin Li        @param html: the HTML that will replace the body of the dialog tab.
44*9c5db199SXin Li        """
45*9c5db199SXin Li        html_esc = html.replace('"', '\\"')
46*9c5db199SXin Li
47*9c5db199SXin Li        # Use JavaScript to set the output.
48*9c5db199SXin Li        self._tab.ExecuteJavaScript('window.__ready = 0; '
49*9c5db199SXin Li                                    'document.body.innerHTML="%s";' % html_esc)
50*9c5db199SXin Li        self._tab.Activate()
51*9c5db199SXin Li        self._tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
52*9c5db199SXin Li
53*9c5db199SXin Li    def clear_output(self):
54*9c5db199SXin Li        """Replace the body of self._tab with a blank screen.
55*9c5db199SXin Li        """
56*9c5db199SXin Li        self.set_tab('')
57*9c5db199SXin Li
58*9c5db199SXin Li    def set_tab_with_buttons(self, html, buttons=['OK']):
59*9c5db199SXin Li        """Replace the body of self._tab with provided html and buttons.
60*9c5db199SXin Li
61*9c5db199SXin Li        @param html: the HTML that will replace the body of the dialog tab.
62*9c5db199SXin Li        @param buttons: the titles of some number of buttons to add to the
63*9c5db199SXin Li                        page. Each button has an integer value, starting from
64*9c5db199SXin Li                        0 for the first. Defaults to an 'OK' button.
65*9c5db199SXin Li        """
66*9c5db199SXin Li        html_total = html+'<br>'
67*9c5db199SXin Li        index = 0
68*9c5db199SXin Li        for title in buttons:
69*9c5db199SXin Li            onclick = 'submit_button(%d)' % index
70*9c5db199SXin Li            html_total += ('<input type="button" value="%s" onclick="%s">' % (
71*9c5db199SXin Li                           cgi.escape(title), onclick))
72*9c5db199SXin Li            index += 1
73*9c5db199SXin Li        self.set_tab(html_total)
74*9c5db199SXin Li
75*9c5db199SXin Li    def set_tab_with_textbox(self, html, title=''):
76*9c5db199SXin Li        """Replace the body of self._tab with provided html and a textbox.
77*9c5db199SXin Li
78*9c5db199SXin Li        Adds a textbox and Submit button to the page.  The value returned after
79*9c5db199SXin Li        clicking the button is the text that was entered in the textbox.
80*9c5db199SXin Li
81*9c5db199SXin Li        @param html: the HTML that will replace the body of the dialog tab.
82*9c5db199SXin Li        @param title: the title put next to the textbox.
83*9c5db199SXin Li        """
84*9c5db199SXin Li        textbox = '%s<input type="text" id="textinput"/>' % title
85*9c5db199SXin Li        button = '<input type="button" value="SUBMIT" onclick="get_text()"/>'
86*9c5db199SXin Li        html_total = '%s<br>%s<br>%s' % (html, textbox, button)
87*9c5db199SXin Li        self.set_tab(html_total)
88*9c5db199SXin Li
89*9c5db199SXin Li    def wait_for_tab_result(self, timeout=_DEFAULT_TIMEOUT):
90*9c5db199SXin Li        """Wait for interactive tab to be ready and get return value.
91*9c5db199SXin Li
92*9c5db199SXin Li        @param timeout: Maximum number of seconds to wait for result.
93*9c5db199SXin Li
94*9c5db199SXin Li        @return: value of window.__result.
95*9c5db199SXin Li        """
96*9c5db199SXin Li        complete = lambda: self._tab.EvaluateJavaScript('window.__ready') == 1
97*9c5db199SXin Li        utils.poll_for_condition(condition=complete, timeout=timeout,
98*9c5db199SXin Li                                 desc='User response')
99*9c5db199SXin Li
100*9c5db199SXin Li        result = self._tab.EvaluateJavaScript('window.__result')
101*9c5db199SXin Li        self._tab.ExecuteJavaScript('window.__ready = 0; '
102*9c5db199SXin Li                                    'window.__result = null;')
103*9c5db199SXin Li        return result
104