[Checkins] SVN: zope.testbrowser/branches/benji-zope.testbrowser.real/ very early code

Benji York benji at zope.com
Tue Sep 4 18:01:32 EDT 2007


Log message for revision 79467:
  very early code
  

Changed:
  U   zope.testbrowser/branches/benji-zope.testbrowser.real/buildout.cfg
  U   zope.testbrowser/branches/benji-zope.testbrowser.real/setup.py
  A   zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.py
  A   zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.txt
  U   zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/tests.py

-=-
Modified: zope.testbrowser/branches/benji-zope.testbrowser.real/buildout.cfg
===================================================================
--- zope.testbrowser/branches/benji-zope.testbrowser.real/buildout.cfg	2007-09-04 21:59:45 UTC (rev 79466)
+++ zope.testbrowser/branches/benji-zope.testbrowser.real/buildout.cfg	2007-09-04 22:01:31 UTC (rev 79467)
@@ -1,5 +1,5 @@
 [buildout]
-develop = .
+develop = . /home/benji/workspace/mozrepl/1
 parts = test
 versions = versions
 find-links = http://download.zope.org/distribution/

Modified: zope.testbrowser/branches/benji-zope.testbrowser.real/setup.py
===================================================================
--- zope.testbrowser/branches/benji-zope.testbrowser.real/setup.py	2007-09-04 21:59:45 UTC (rev 79466)
+++ zope.testbrowser/branches/benji-zope.testbrowser.real/setup.py	2007-09-04 22:01:31 UTC (rev 79467)
@@ -48,7 +48,8 @@
     tests_require = ['zope.testing'],
     install_requires = ['setuptools',
                         'mechanize',
-                        'ClientForm'],
+                        'ClientForm',
+                        'mozrepl'],
     extras_require = dict(
         test = ['zope.interface',
                 'zope.schema',

Added: zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.py
===================================================================
--- zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.py	                        (rev 0)
+++ zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.py	2007-09-04 22:01:31 UTC (rev 79467)
@@ -0,0 +1,315 @@
+from zope.testbrowser import interfaces
+import re
+import simplejson
+import telnetlib
+import time
+import zope.interface
+import zope.testbrowser.browser
+import ClientForm
+
+PROMPT = re.compile('repl\d?> ')
+
+class Browser(zope.testbrowser.browser.SetattrErrorsMixin):
+    zope.interface.implements(interfaces.IBrowser)
+
+    raiseHttpErrors = True
+    _counter = 0
+
+    def __init__(self, url=None, host='localhost', port=4242):
+        self.timer = zope.testbrowser.browser.PystoneTimer()
+        self.init_repl(host, port)
+        self._enable_setattr_errors = True
+
+        if url is not None:
+            self.open(url)
+
+    def init_repl(self, host, port):
+        self.telnet = telnetlib.Telnet(host, port)
+        self.telnet.write("""
+            var tb_tokens = {};
+            var tb_next_token = 0;
+            function tb_get_link_by_predicate(predicate, index) {
+                var anchors = content.document.getElementsByTagName('a');
+                var i=0;
+                var found = null;
+                if (index == undefined) index = null;
+                for (x=0; x < anchors.length; x++) {
+                    a = anchors[x];
+                    if (!predicate(a)) {
+                        continue;
+                    }
+                    // this anchor matches
+
+                    // if we weren't given an index, but we found more than
+                    // one match, we have an ambiguity
+                    if (index == null && i > 0) {
+                        return 'ambiguity error';
+                    }
+
+                    found = x;
+
+                    // if we were given an index and we just found it, stop
+                    if (index != null && i == index) {
+                        break
+                    }
+                    i++;
+                }
+                if (found != null) {
+                    tb_tokens[tb_next_token] = anchors[found];
+                    return tb_next_token++;
+                }
+                return false; // link not found
+            }
+
+            function tb_get_link_by_text(text, index) {
+                return tb_get_link_by_predicate(
+                    function (a) {
+                        return a.textContent.indexOf(text) == 0;
+                    }, index)
+            }
+
+            function tb_get_link_by_id(id, index) {
+                return tb_get_link_by_predicate(
+                    function (a) {
+                        return a.id == id;
+                    }, index)
+            }
+
+            function tb_get_link_by_url(url, index) {
+                return tb_get_link_by_predicate(
+                    function (a) {
+                        return a.href.indexOf(url) == 0;
+                    }, index)
+            }
+            """)
+
+    def execute(self, js):
+        if not js.strip():
+            return
+        self.telnet.write("'MARKER'")
+        self.telnet.read_until('MARKER')
+        self.expect([PROMPT])
+        self.telnet.write(js)
+        i, match, text = self.expect([PROMPT])
+        result = text.rsplit('\n', 1)
+        if len(result) == 1:
+            return None
+        else:
+            return result[0]
+
+    def executeLines(self, js):
+        lines = js.split('\n')
+        for line in lines:
+            self.execute(line)
+
+    def expect(self, res, timeout=1):
+        i, match, text = self.telnet.expect([PROMPT], timeout)
+        if match is None:
+            import pdb;pdb.set_trace()
+            raise RuntimeError('unexpected result from MozRepl')
+        return i, match, text
+
+    def _changed(self):
+        self._counter += 1
+
+    @property
+    def url(self):
+        return self.execute('content.location')
+
+    def _primePageLoadWait(self):
+        # save the current document element to compare against later
+        self.execute('tb_prev_document = content.document.documentElement;')
+
+    def _waitForPageLoad(self):
+        # wait for the page to load
+        while self.execute('content.document.documentElement'
+            '.isSameNode(tb_prev_document)') == 'true':
+                time.sleep(0.001)
+
+    def open(self, url, data=None):
+        assert data is None
+        self.start_timer()
+        try:
+            self._primePageLoadWait()
+            self.execute('content.location = ' + simplejson.dumps(url))
+            self._waitForPageLoad()
+        finally:
+            self.stop_timer()
+            self._changed()
+
+        # TODO raise non-200 errors
+
+    @property
+    def isHtml(self):
+        return self.execute('content.document.contentType') == 'text/html'
+
+    @property
+    def title(self):
+        return self.execute('content.document.title')
+
+    @property
+    def contents(self):
+        return self.execute('content.document.documentElement.innerHTML')
+
+    @property
+    def headers(self):
+        raise NotImplementedError
+
+    @apply
+    def handleErrors():
+        def get(self):
+            raise NotImplementedError
+
+        def set(self, value):
+            raise NotImplementedError
+
+        return property(get, set)
+
+    def start_timer(self):
+        self.timer.start()
+
+    def stop_timer(self):
+        self.timer.stop()
+
+    @property
+    def lastRequestPystones(self):
+        return self.timer.elapsedPystones
+
+    @property
+    def lastRequestSeconds(self):
+        return self.timer.elapsedSeconds
+
+    def reload(self):
+        self.start_timer()
+        self._primePageLoadWait()
+        self.execute('content.document.location = content.document.location')
+        self._waitForPageLoad()
+        self.stop_timer()
+
+    def goBack(self, count=1):
+        self.start_timer()
+        self._primePageLoadWait()
+        self.execute('content.back()')
+        self._waitForPageLoad()
+        self.stop_timer()
+        self._changed()
+
+    def addHeader(self, key, value):
+        raise NotImplementedError
+
+    def getLink(self, text=None, url=None, id=None, index=None):
+        zope.testbrowser.browser.onlyOne((text, url, id), 'text, url, or id')
+        js_index = simplejson.dumps(index)
+        if text is not None:
+            msg = 'text %r' % text
+            token = self.execute('tb_get_link_by_text(%s, %s)'
+                 % (simplejson.dumps(text), js_index))
+        elif url is not None:
+            msg = 'url %r' % url
+            token = self.execute('tb_get_link_by_text(%s, %s)'
+                 % (simplejson.dumps(url), js_index))
+        elif id is not None:
+            msg = 'id %r' % id
+            token = self.execute('tb_get_link_by_id(%s, %s)'
+                 % (simplejson.dumps(id), js_index))
+
+        if token == 'false':
+            raise ValueError('Link not found: ' + msg)
+        if token == 'ambiguity error':
+            raise ClientForm.AmbiguityError(msg)
+
+        return Link(token, self)
+
+    def _follow_link(self, token):
+        self.execute('tb_follow_link(%s)' % token)
+
+    def getControl(self, label=None, name=None, index=None):
+        raise NotImplementedError
+
+    def getForm(self, id=None, name=None, action=None, index=None):
+        raise NotImplementedError
+
+
+class Link(zope.testbrowser.browser.SetattrErrorsMixin):
+    zope.interface.implements(interfaces.ILink)
+
+    def __init__(self, token, browser):
+        self.token = token
+        self.browser = browser
+        self._browser_counter = self.browser._counter
+        self._enable_setattr_errors = True
+
+    def click(self):
+        if self._browser_counter != self.browser._counter:
+            raise interfaces.ExpiredError
+        self.browser._start_timer()
+        self.browser._follow_link(self.token)
+        self.browser._stop_timer()
+        self.browser._changed()
+
+    @property
+    def url(self):
+        return self.browser.execute('tb_tokens[%s].href' % self.token)
+
+    @property
+    def text(self):
+        return self.browser.execute('tb_tokens[%s].textContent' % self.token)
+
+    @property
+    def tag(self):
+        raise NotImplementedError
+
+    @property
+    def attrs(self):
+        raise NotImplementedError
+
+    def __repr__(self):
+        return "<%s text=%r url=%r>" % (
+            self.__class__.__name__, self.text, self.url)
+
+    def _follow_link(self, token):
+        self.execute('tb_follow_link(%s)' % token)
+
+    def getControl(self, label=None, name=None, index=None):
+        raise NotImplementedError
+
+    def getForm(self, id=None, name=None, action=None, index=None):
+        raise NotImplementedError
+
+
+class Link(zope.testbrowser.browser.SetattrErrorsMixin):
+    zope.interface.implements(interfaces.ILink)
+
+    def __init__(self, token, browser):
+        self.token = token
+        self.browser = browser
+        self._browser_counter = self.browser._counter
+        self._enable_setattr_errors = True
+
+    def click(self):
+        if self._browser_counter != self.browser._counter:
+            raise interfaces.ExpiredError
+        self.browser._start_timer()
+        self.browser._follow_link(self.token)
+        self.browser._stop_timer()
+        self.browser._changed()
+
+    @property
+    def url(self):
+        return self.browser.execute('tb_tokens[%s].href' % self.token)
+
+    @property
+    def text(self):
+        return self.browser.execute('tb_tokens[%s].textContent' % self.token)
+
+    @property
+    def tag(self):
+        raise NotImplementedError
+
+    @property
+    def attrs(self):
+        raise NotImplementedError
+
+    def __repr__(self):
+        return "<%s text=%r url=%r>" % (
+            self.__class__.__name__, self.text, self.url)


Property changes on: zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.txt
===================================================================
--- zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.txt	                        (rev 0)
+++ zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.txt	2007-09-04 22:01:31 UTC (rev 79467)
@@ -0,0 +1,33 @@
+    >>> from zope.testbrowser.real import Browser
+
+    >>> browser = Browser(host='192.168.1.103')
+
+#    >>> browser = Browser(host='192.168.23.210')
+
+    >>> browser.open('http://images.google.com')
+    >>> browser.url
+    'http://images.google.com/'
+    >>> browser.open('http://google.com')
+    >>> browser.url
+    'http://www.google.com/'
+
+    >>> browser.isHtml
+    True
+
+    >>> browser.title
+    'Google'
+
+    >>> browser.contents
+    '<head>...</body>'
+
+    >>> browser.reload()
+    >>> browser.url
+    'http://www.google.com/'
+    >>> browser.goBack()
+    >>> browser.url
+    'http://images.google.com/'
+
+    >>> browser.getLink('Preferences')
+    <Link text='Preferences' url='http://images.google.com/preferences?hl=en'>
+
+#    >>> browser.getLink(url='http://news.google.com')


Property changes on: zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/real.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/tests.py
===================================================================
--- zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/tests.py	2007-09-04 21:59:45 UTC (rev 79466)
+++ zope.testbrowser/branches/benji-zope.testbrowser.real/src/zope/testbrowser/tests.py	2007-09-04 22:01:31 UTC (rev 79467)
@@ -383,12 +383,17 @@
 def test_suite():
     from zope.testing import doctest
     flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
+
     readme = FunctionalDocFileSuite('README.txt', optionflags=flags,
         checker=checker)
     readme.layer = TestBrowserLayer
-    wire = FunctionalDocFileSuite('over_the_wire.txt', optionflags=flags)
+
+    wire = doctest.DocFileSuite('over_the_wire.txt', optionflags=flags)
     wire.level = 2
-    wire.layer = TestBrowserLayer
+
+    wire = doctest.DocFileSuite('real.txt', optionflags=flags)
+    wire.level = 3
+
     this_file = doctest.DocTestSuite(checker=checker)
     return unittest.TestSuite((this_file, readme, wire))
 



More information about the Checkins mailing list