Skip to content
This repository
Browse code

add uitest

git-svn-id: https://pyjamas.svn.sourceforge.net/svnroot/pyjamas/trunk@2226 7a2bd370-bda8-463c-979e-2900ccfb811e
  • Loading branch information...
commit be168721c5a34982e4188f58c3a3f9ef1b8b1958 1 parent 61c4c33
authored November 08, 2009
20  examples/uitest/LabelTest.py
... ...
@@ -0,0 +1,20 @@
  1
+from pyjamas.ui.RootPanel import RootPanel
  2
+from pyjamas.ui.Label import Label
  3
+
  4
+from UnitTest import UnitTest
  5
+
  6
+from __pyjamas__ import doc
  7
+
  8
+class LabelTest(UnitTest):
  9
+
  10
+    def testLabelAdd(self):
  11
+        self.l = Label("Hello World (label)", StyleName='teststyle')
  12
+        RootPanel().add(self.l)
  13
+        ht = doc().body.innerHTML
  14
+        self.write_test_output(ht, 'addlabel')
  15
+
  16
+        if not RootPanel().remove(self.l):
  17
+            self.fail("Label added but apparently not owned by RootPanel()")
  18
+        ht = doc().body.innerHTML
  19
+        self.write_test_output(ht, 'removelabel')
  20
+
278  examples/uitest/UnitTest.py
... ...
@@ -0,0 +1,278 @@
  1
+from write import write, writebr
  2
+import sys
  3
+
  4
+IN_BROWSER = sys.platform in ['mozilla', 'ie6', 'opera', 'oldmoz', 'safari']
  5
+IN_JS = sys.platform in ['mozilla', 'ie6', 'opera', 'oldmoz',
  6
+                         'safari', 'spidermonkey', 'pyv8']
  7
+
  8
+from pyjamas.Timer import Timer
  9
+
  10
+from pyjamas.HTTPRequest import HTTPRequest
  11
+
  12
+class GetTestOutput:
  13
+
  14
+    def __init__(self, unittest, test_name, output):
  15
+        self.test_name = test_name
  16
+        self.unittest = unittest
  17
+        self.output = output
  18
+
  19
+    def onCompletion(self, responseText):
  20
+        # TODO - cope with unicode / utf-8 test results
  21
+        print "onCompletion", self.unittest.tests_outstanding, self.test_name
  22
+        self.unittest.async_test_name = self.test_name
  23
+        self.unittest.assertEqual(responseText, str(self.output))
  24
+        self.unittest.tests_outstanding -= 1
  25
+
  26
+    def onError(self, responseText, status):
  27
+        self.unittest.async_test_name = self.test_name
  28
+        self.unittest.fail("""downloading test output %s failed,
  29
+status %s, response %s""" % (self.test_name, str(status), repr(responseText)))
  30
+        self.unittest.tests_outstanding -= 1
  31
+
  32
+class UnitTest:
  33
+
  34
+    def __init__(self, test_gen_folder):
  35
+        self.test_gen_folder = test_gen_folder
  36
+        self.tests_completed=0
  37
+        self.tests_failed=0
  38
+        self.tests_passed=0
  39
+        self.test_methods=[]
  40
+        self.test_idx = None
  41
+        self.tests_outstanding = None
  42
+
  43
+        # Synonyms for assertion methods
  44
+        self.assertEqual = self.assertEquals = self.failUnlessEqual
  45
+        self.assertNotEqual = self.assertNotEquals = self.failIfEqual
  46
+        self.assertAlmostEqual = self.assertAlmostEquals = self.failUnlessAlmostEqual
  47
+        self.assertNotAlmostEqual = self.assertNotAlmostEquals = self.failIfAlmostEqual
  48
+        self.assertRaises = self.failUnlessRaises
  49
+        self.assert_ = self.assertTrue = self.failUnless
  50
+        self.assertFalse = self.failIf
  51
+
  52
+    def do_test(self, output, name):
  53
+        handler = GetTestOutput(self, self.current_test_name, output)
  54
+        if name:
  55
+            fname = "%s.%s.txt" % (self.current_test_name, name)
  56
+        else:
  57
+            fname = "%s.txt" % self.current_test_name
  58
+        HTTPRequest().asyncGet(fname, handler)
  59
+
  60
+    def write_test_output(self, output, name=None):
  61
+        if self.test_gen_folder is None:
  62
+            if self.tests_outstanding is None:
  63
+                self.tests_outstanding = 0
  64
+            self.tests_outstanding += 1
  65
+            self.do_test(output, name)
  66
+            return
  67
+
  68
+        # otherwise assume we're running pyjd, and have file-system
  69
+        # access
  70
+        import os
  71
+        if name:
  72
+            fname = "%s.%s.txt" % (self.current_test_name, name)
  73
+        else:
  74
+            fname = "%s.txt" % self.current_test_name
  75
+        f = open(os.path.join(self.test_gen_folder, fname), "w")
  76
+        f.write(output)
  77
+        f.close()
  78
+
  79
+        return False
  80
+
  81
+    def _run_test(self, test_method_name):
  82
+        self.getTestMethods()
  83
+
  84
+        test_method=getattr(self, test_method_name)
  85
+        self.current_test_name = test_method_name
  86
+        self.setUp()
  87
+        test_method()
  88
+        self.tearDown()
  89
+        self.current_test_name = None
  90
+        self.async_test_name = None
  91
+
  92
+    def run(self):
  93
+        self.getTestMethods()
  94
+        #if not IN_BROWSER:
  95
+        #    for test_method_name in self.test_methods:
  96
+        #        self._run_test(test_method_name)
  97
+        #    self.displayStats()
  98
+        #    if hasattr(self, "start_next_test"):
  99
+        #        self.check_start_next_test()
  100
+        #    return
  101
+        self.test_idx = 0
  102
+        Timer(1, self)
  103
+
  104
+    def onTimer(self, tid):
  105
+        print self.test_idx
  106
+        if self.test_idx is 'DONE':
  107
+            self.check_start_next_test()
  108
+            return
  109
+
  110
+        for i in range(10):
  111
+            if self.test_idx >= len(self.test_methods):
  112
+                self.test_idx = 'DONE'
  113
+                self.check_start_next_test()
  114
+                return
  115
+
  116
+            self._run_test(self.test_methods[self.test_idx])
  117
+            self.test_idx += 1
  118
+        Timer(1, self)
  119
+
  120
+    def check_start_next_test(self):
  121
+        if self.tests_outstanding is None:
  122
+            return
  123
+        if self.tests_outstanding == 0:
  124
+            self.displayStats()
  125
+            self.start_next_test()
  126
+            return
  127
+        # do it again.
  128
+        Timer(100, self)
  129
+    
  130
+    def setUp(self):
  131
+        pass
  132
+
  133
+    def tearDown(self):
  134
+        pass
  135
+
  136
+    def getName(self):
  137
+        return self.__class__.__name__
  138
+
  139
+    def getNameFmt(self, msg=""):
  140
+        test_name = self.async_test_name or self.current_test_name
  141
+        if self.getName():
  142
+            if msg:
  143
+                msg=" " + str(msg)
  144
+            if test_name:
  145
+                msg += " (%s) " % test_name
  146
+            return self.getName() + msg + ": "
  147
+        return ""
  148
+
  149
+    def getTestMethods(self):
  150
+        self.test_methods=[]
  151
+        for m in dir(self):
  152
+            if self.isTestMethod(m):
  153
+                self.test_methods.append(m)
  154
+
  155
+    def isTestMethod(self, method):
  156
+        if callable(getattr(self, method)):
  157
+            if method.find("test") == 0:
  158
+                return True
  159
+        return False
  160
+
  161
+    def fail(self, msg=None):
  162
+        self.startTest()
  163
+        self.tests_failed+=1
  164
+
  165
+        if not msg:
  166
+            msg="assertion failed"
  167
+        else:
  168
+            msg = str(msg)
  169
+
  170
+        title="<b>" + self.getNameFmt("Test failed") + "</b>"
  171
+        writebr(title + msg)
  172
+        if sys.platform in ['mozilla', 'ie6', 'opera', 'oldmoz', 'safari']:
  173
+            from __pyjamas__ import JS
  174
+            JS("""if (typeof console != 'undefined') {
  175
+                if (typeof console.error == 'function') console.error(msg);
  176
+                if (typeof console.trace == 'function') console.trace();
  177
+            }""")
  178
+        return False
  179
+
  180
+    def startTest(self):
  181
+        self.tests_completed+=1
  182
+
  183
+    def failIf(self, expr, msg=None):
  184
+        self.startTest()
  185
+        if expr:
  186
+            return self.fail(msg)
  187
+
  188
+    def failUnless(self, expr, msg=None):
  189
+        self.startTest()
  190
+        if not expr:
  191
+            return self.fail(msg)
  192
+
  193
+    def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
  194
+        try:
  195
+            callableObj(*args, **kwargs)
  196
+        except excClass:
  197
+            return
  198
+        else:
  199
+            if hasattr(excClass,'__name__'): excName = excClass.__name__
  200
+            else: excName = str(excClass)
  201
+            #raise self.failureException, "%s not raised" % excName
  202
+            self.fail("%s not raised" % excName)
  203
+
  204
+    def failUnlessEqual(self, first, second, msg=None):
  205
+        self.startTest()
  206
+        if not first == second:
  207
+            if not msg:
  208
+                msg=repr(first) + " != " + repr(second)
  209
+            return self.fail(msg)
  210
+
  211
+    def failIfEqual(self, first, second, msg=None):
  212
+        self.startTest()
  213
+        if first == second:
  214
+            if not msg:
  215
+                msg=repr(first) + " == " + repr(second)
  216
+            return self.fail(msg)
  217
+
  218
+    def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
  219
+        self.startTest()
  220
+        if round(second-first, places) != 0:
  221
+            if not msg:
  222
+                msg=repr(first) + " != " + repr(second) + " within " + repr(places) + " places"
  223
+            return self.fail(msg)
  224
+
  225
+    def failIfAlmostEqual(self, first, second, places=7, msg=None):
  226
+        self.startTest()
  227
+        if round(second-first, places)  is  0:
  228
+            if not msg:
  229
+                msg=repr(first) + " == " + repr(second) + " within " + repr(places) + " places"
  230
+            return self.fail(msg)
  231
+
  232
+    # based on the Python standard library
  233
+    def assertRaises(self, excClass, callableObj, *args, **kwargs):
  234
+        """
  235
+        Fail unless an exception of class excClass is thrown
  236
+        by callableObj when invoked with arguments args and keyword
  237
+        arguments kwargs. If a different type of exception is
  238
+        thrown, it will not be caught, and the test case will be
  239
+        deemed to have suffered an error, exactly as for an
  240
+        unexpected exception.
  241
+        """
  242
+        self.startTest()
  243
+        try:
  244
+            callableObj(*args, **kwargs)
  245
+        except excClass, exc:
  246
+            return
  247
+        else:
  248
+            if hasattr(excClass, '__name__'):
  249
+                excName = excClass.__name__
  250
+            else:
  251
+                excName = str(excClass)
  252
+            self.fail("%s not raised" % excName)
  253
+
  254
+    def displayStats(self):
  255
+        if self.tests_failed:
  256
+            bg_colour="#ff0000"
  257
+            fg_colour="#ffffff"
  258
+        else:
  259
+            bg_colour="#00ff00"
  260
+            fg_colour="#000000"
  261
+
  262
+        tests_passed=self.tests_completed - self.tests_failed
  263
+        if sys.platform in ['mozilla', 'ie6', 'opera', 'oldmoz', 'safari']:
  264
+            output="<table cellpadding=4 width=100%><tr><td bgcolor='" + bg_colour + "'><font face='arial' size=4 color='" + fg_colour + "'><b>"
  265
+        else:
  266
+            output = ""
  267
+        output+=self.getNameFmt() + "Passed %d " % tests_passed + "/ %d" % self.tests_completed + " tests"
  268
+
  269
+        if self.tests_failed:
  270
+            output+=" (%d failed)" % self.tests_failed
  271
+
  272
+        if sys.platform in ['mozilla', 'ie6', 'opera', 'oldmoz', 'safari']:
  273
+            output+="</b></font></td></tr></table>"
  274
+        else:
  275
+            output+= "\n"
  276
+
  277
+        write(output)
  278
+
7  examples/uitest/build.sh
... ...
@@ -0,0 +1,7 @@
  1
+#!/bin/sh
  2
+# you will need to read the top level README, and run boostrap.py
  3
+# and buildout in order to make pyjsbuild
  4
+
  5
+options="$*"
  6
+if [ -z $options ] ; then options="-O";fi
  7
+../../bin/pyjsbuild --print-statements $options uitest.py
3  examples/uitest/public/testLabelAdd.addlabel.txt
... ...
@@ -0,0 +1,3 @@
  1
+<pre>Unit Tests will appear and disappear.</pre>
  2
+<script language="javascript" src="bootstrap.js"></script>
  3
+<div style="white-space: normal;" class="teststyle">Hello World (label)</div>
2  examples/uitest/public/testLabelAdd.removelabel.txt
... ...
@@ -0,0 +1,2 @@
  1
+<pre>Unit Tests will appear and disappear.</pre>
  2
+<script language="javascript" src="bootstrap.js"></script>
7  examples/uitest/public/uitest.css
... ...
@@ -0,0 +1,7 @@
  1
+.teststyle {
  2
+  font-size: 200%;
  3
+  margin: 20px;
  4
+  padding: 20px;
  5
+  background-color: #00ff00;
  6
+}
  7
+
13  examples/uitest/public/uitest.html
... ...
@@ -0,0 +1,13 @@
  1
+<html>
  2
+    <!-- auto-generated html - you should consider editing and
  3
+         adapting this to suit your requirements
  4
+     -->
  5
+    <head>
  6
+      <meta name="pygwt:module" content="uitest">
  7
+      <link rel='stylesheet' href='uitest.css'>
  8
+      <title>my titlePyJamas Auto-Generated HTML file uitest</title>
  9
+    </head>
  10
+<body bgcolor="white"><pre>Unit Tests will appear and disappear.</pre>
  11
+<script language="javascript" src="bootstrap.js"></script>
  12
+</body>
  13
+</html>
65  examples/uitest/uitest.py
... ...
@@ -0,0 +1,65 @@
  1
+import pyjd # this is dummy in pyjs.
  2
+from pyjamas.ui.RootPanel import RootPanel
  3
+from pyjamas.Timer import Timer
  4
+
  5
+from __pyjamas__ import doc
  6
+
  7
+from UnitTest import IN_BROWSER, IN_JS, IN_BROWSER
  8
+
  9
+from LabelTest import LabelTest
  10
+
  11
+import write
  12
+import sys
  13
+
  14
+class RunTests:
  15
+    def __init__(self, test_gen):
  16
+        self.current_test = None
  17
+        self.test_gen = test_gen
  18
+        self.testlist = {}
  19
+        self.test_idx = 0
  20
+        Timer(100, self)
  21
+
  22
+    def add(self, test):
  23
+        self.testlist[len(self.testlist)] = test
  24
+
  25
+    def onTimer(self, tid):
  26
+        self.start_test()
  27
+
  28
+    def start_test(self):
  29
+        if self.test_idx >= len(self.testlist):
  30
+            print "num tests outstanding", self.current_test.tests_outstanding
  31
+            if self.current_test.tests_outstanding > 0:
  32
+                Timer(100, self)
  33
+                return
  34
+
  35
+            write.display_log_output()
  36
+            return
  37
+
  38
+        idx = self.test_idx
  39
+        self.test_idx += 1
  40
+
  41
+        test_kls = self.testlist[idx]
  42
+        t = test_kls(self.test_gen)
  43
+        self.current_test = t
  44
+        t.start_next_test = getattr(self, "start_test")
  45
+        t.run()
  46
+
  47
+def main(test_gen_out):
  48
+
  49
+    pyjd.setup("public/uitest.html")
  50
+    t = RunTests(test_gen_out)
  51
+    t.add(LabelTest)
  52
+    pyjd.run()
  53
+
  54
+if __name__ == '__main__':
  55
+
  56
+    # set the test output folder using e.g. hulahop, create
  57
+    # the output to be used by tests.
  58
+
  59
+    test_gen_output_folder = None
  60
+    if hasattr(sys, 'argv'):
  61
+        if len(sys.argv) == 2:
  62
+            test_gen_output_folder = sys.argv[1]
  63
+        
  64
+    main(test_gen_output_folder )
  65
+
21  examples/uitest/write.py
... ...
@@ -0,0 +1,21 @@
  1
+data = ""
  2
+global element
  3
+
  4
+from __pyjamas__ import doc, escape
  5
+
  6
+def display_log_output():
  7
+    global element
  8
+    global data
  9
+    element = doc().createElement("div")
  10
+    doc().body.appendChild(element)
  11
+    element.innerHTML = escape(data)
  12
+
  13
+def write(text):
  14
+    global data
  15
+    data += text
  16
+
  17
+    print "data", data
  18
+
  19
+def writebr(text):
  20
+    write(text + "<br />\n")
  21
+
9  library/__pyjamas__.py
@@ -14,7 +14,14 @@
14 14
 def noSourceTracking(*args):
15 15
     pass
16 16
 
17  
-def unescape(str):
  17
+def escape(s):
  18
+    s = s.replace("&", "&amp;")
  19
+    s = s.replace("<", "&lt;")
  20
+    s = s.replace(">", "&gt;")
  21
+    s = s.replace('"', "&quot;")
  22
+    return s
  23
+
  24
+def unescape(s):
18 25
     s = s.replace("&amp;", "&")
19 26
     s = s.replace("&lt;", "<")
20 27
     s = s.replace("&gt;", ">")
4  library/pyjamas/HTTPRequest.py
@@ -17,7 +17,9 @@ def __init__(self, htr, mode, user, pwd, url, postData=None, handler=None,
17 17
 
18 18
     def callback(self):
19 19
         if self.mode == 'GET':
20  
-            return self.htr.asyncGetImpl(self.user, self.pwd, self.url, self.handler)
  20
+            return self.htr.asyncGetImpl(self.user, self.pwd, self.url,
  21
+                                         self.handler,
  22
+                                         self.return_xml, self.content_type)
21 23
         else:
22 24
             return self.htr.asyncPostImpl(self.user, self.pwd, self.url,
23 25
                                          self.postData, self.handler,
10  library/pyjamas/Window.py
@@ -116,7 +116,10 @@ def fireClosedAndCatch(handler):
116 116
 
117 117
 def fireClosedImpl():
118 118
     for listener in closingListeners:
119  
-        listener.onWindowClosed()
  119
+        if hasattr(listener, 'onWindowClosed'):
  120
+            listener.onWindowClosed()
  121
+        else:
  122
+            listener()
120 123
 
121 124
 def fireClosingAndCatch(handler):
122 125
     # FIXME - need implementation
@@ -135,7 +138,10 @@ def resizeBy(width, height):
135 138
 def fireClosingImpl():
136 139
     ret = None
137 140
     for listener in closingListeners:
138  
-        msg = listener.onWindowClosing()
  141
+        if hasattr(listener, 'onWindowClosing'):
  142
+            msg = listener.onWindowClosing()
  143
+        else:
  144
+            msg = listener()
139 145
         if ret is None:
140 146
             ret = msg
141 147
     return ret
71  library/pyjamas/ui/RootPanel.py
@@ -22,6 +22,39 @@
22 22
 from AbsolutePanel import AbsolutePanel
23 23
 
24 24
 rootPanels = {}
  25
+class RootPanelManager:
  26
+
  27
+    def onWindowClosed(self):
  28
+        for panel in rootPanels.itervalues():
  29
+            panel.onDetach()
  30
+
  31
+    def onWindowClosing(self):
  32
+        return None
  33
+
  34
+panelManager = None
  35
+
  36
+def get(id=None):
  37
+    """
  38
+
  39
+    """
  40
+    if rootPanels.has_key(id):
  41
+        return rootPanels[id]
  42
+
  43
+    element = None
  44
+    if id:
  45
+        element = DOM.getElementById(id)
  46
+        if not element:
  47
+            return None
  48
+
  49
+    if len(rootPanels) < 1:
  50
+        global panelManager
  51
+        if panelManager is None:
  52
+            panelManger = RootPanelManager()
  53
+        Window.addWindowCloseListener(panelManager)
  54
+
  55
+    panel = RootPanelCls(element)
  56
+    rootPanels[id] = panel
  57
+    return panel
25 58
 
26 59
 class RootPanelCls(AbsolutePanel):
27 60
     def __init__(self, Element=None):
@@ -35,44 +68,8 @@ def __init__(self, Element=None):
35 68
     def getBodyElement(self):
36 69
         return doc().body
37 70
 
38  
-    @classmethod
39  
-    def get(cls, id=None):
40  
-        """
41  
-
42  
-        """
43  
-        if rootPanels.has_key(id):
44  
-            return rootPanels[id]
45  
-
46  
-        element = None
47  
-        if id:
48  
-            element = DOM.getElementById(id)
49  
-            if not element:
50  
-                return None
51  
-
52  
-        if len(rootPanels) < 1:
53  
-            cls.hookWindowClosing()
54  
-
55  
-        panel = RootPanel(element)
56  
-        rootPanels[id] = panel
57  
-        return panel
58  
-
59  
-    @classmethod
60  
-    def hookWindowClosing(cls):
61  
-        Window.addWindowCloseListener(cls)
62  
-
63  
-    @classmethod
64  
-    def onWindowClosed(cls):
65  
-        for panel in rootPanels.itervalues():
66  
-            panel.onDetach()
67  
-
68  
-    @classmethod
69  
-    def onWindowClosing(cls):
70  
-        return None
71  
-
72 71
 Factory.registerClass('pyjamas.ui.RootPanelCls', RootPanelCls)
73 72
 
74 73
 def RootPanel(element=None):
75  
-    if isinstance(element, str):
76  
-        return RootPanelCls().get(element)
77  
-    return RootPanelCls(element)
  74
+    return get(element)
78 75
 

0 notes on commit be16872

Please sign in to comment.
Something went wrong with that request. Please try again.