1import os
2import unittest
3from threading import Thread
4from time import sleep
5
6from .browser_base import TextExtractionMixin
7
8SELENIUM = 'MOZ_HEADLESS' in os.environ
9
10try:
11    from selenium import webdriver
12    from selenium.webdriver.firefox.options import Options
13except ImportError:
14    SELENIUM = False
15
16if SELENIUM:
17    from urllib.parse import urlunsplit
18    from http.server import HTTPServer, BaseHTTPRequestHandler
19    from queue import Queue
20
21    class BaseTestRequestHandler(BaseHTTPRequestHandler):
22        _last_html = ''
23
24        def _get_last_html(self):
25            q = self.server.html_queue
26            while not q.empty():
27                self._last_html = q.get_nowait()
28            return self._last_html
29
30        def log_request(self, code='-', size='-'):
31            pass
32
33        def recv_from_testsuite(self, non_blocking=False):
34            q = self.server.in_queue
35            if non_blocking:
36                return None if q.empty() else q.get_nowait()
37            return q.get()
38
39        def send_to_testsuite(self, value):
40            self.server.out_queue.put(value)
41
42    class HTMLSnippetSender(BaseTestRequestHandler):
43        last_html = b''
44
45        def get_last_html(self):
46            while True:
47                value = self.recv_from_testsuite(non_blocking=True)
48                if value is None:
49                    break
50                self.last_html = value
51            return self.last_html
52
53        def do_GET(self):
54            if self.path == '/':
55                self.send_response(200)
56                self.send_header('Content-Type', 'text/html; charset=utf-8')
57                self.end_headers()
58                self.wfile.write(self.get_last_html().encode('utf-8'))
59            else:
60                self.send_response(404)
61                self.end_headers()
62
63    class BaseBrowserTest(unittest.TestCase):
64        LOCAL_IP = '127.0.0.1'
65        PORT = 28546
66        # descendant of BaseBrowserTestRequestHandler
67        REQUEST_HANDLER_CLASS = None
68
69        @classmethod
70        def setUpClass(cls):
71            cls.to_server_queue = Queue()
72            cls.from_server_queue = Queue()
73            cls.server = HTTPServer((cls.LOCAL_IP, cls.PORT),
74                                    cls.REQUEST_HANDLER_CLASS)
75            cls.server.in_queue = cls.to_server_queue
76            cls.server.out_queue = cls.from_server_queue
77            cls.server_thread = Thread(target=cls.server.serve_forever)
78            cls.server_thread.daemon = True
79            cls.server_thread.start()
80            options = Options()
81            options.add_argument('-headless')
82            cls.driver = webdriver.Firefox(options=options)
83            sleep(1)
84
85        @classmethod
86        def tearDownClass(cls):
87            cls.driver.quit()
88            cls.server.shutdown()
89            cls.server.server_close()
90
91        def send_to_server(self, value):
92            self.to_server_queue.put(value)
93
94        def recv_from_server(self, non_blocking=False):
95            q = self.from_server_queue
96            if non_blocking:
97                return None if q.empty() else q.get_nowait()
98            return q.get()
99
100        def open_url(self, path):
101            self.driver.get(urlunsplit(
102                ('http', '{}:{}'.format(
103                    self.LOCAL_IP, self.PORT), path, '', '')))
104
105    class TestInnerText(BaseBrowserTest, TextExtractionMixin):
106        REQUEST_HANDLER_CLASS = HTMLSnippetSender
107
108        def _simple_test(self, html, expected_sq, expected_nosq, **kwargs):
109            self.send_to_server(html)
110            self.open_url('/')
111
112            selenium_text = self.driver.find_element_by_tag_name('body').text
113            self.assertEqual(selenium_text, expected_sq)
114
115            #  inner_text = self.driver.execute_script(
116            #    'return document.body.innerText')
117            #  text_content = self.driver.execute_script(
118            #    'return document.body.textContent')
119