Skip to content

Instantly share code, notes, and snippets.

@datakurre
Created October 11, 2011 17:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save datakurre/1278704 to your computer and use it in GitHub Desktop.
Save datakurre/1278704 to your computer and use it in GitHub Desktop.
plone.app.testing javascripts with coffee-script-doctests using zombie.js
import doctest
import subprocess
from plone.app.testing import TEST_USER_NAME, TEST_USER_PASSWORD
def browser(url, debug=False):
def decorator(func):
def wrapper(*args):
parser = doctest.DocTestParser()
checker = doctest.OutputChecker()
options = doctest.NORMALIZE_WHITESPACE + doctest.ELLIPSIS
mapping = {
"TEST_USER_NAME": TEST_USER_NAME,
"TEST_USER_PASSWORD": TEST_USER_PASSWORD
}
test = doctest.DocTest(
parser.get_examples(func.__doc__ % mapping), {},
func.func_name, func.__code__.co_filename,
func.__code__.co_firstlineno, func.__doc__)
beginning = u"""\
async = require "async"
zombie = require "zombie"
browser = new zombie.Browser
browser.setMaxListeners(100)
# on every 'all events done', update globals from browser.window
do ->
global_keys = []
browser.on "done", (browser) ->
for own key in global_keys
global[key] = undefined
delete global[key]
global_keys = []
for own key of browser.window
global[key] = browser.window[key]
global_keys.push key
# perform serial processing of doctest examples
async.series [
(async_callback) ->
browser.location = "%s"
do async_callback
""" % url
step_sep = ("-" * 80)
step_start = u"""\
(async_callback) ->
console.log "%s"
browser.wait (err, browser, status) ->
""" % step_sep
step_end = u"do async_callback\n"
end = u"""\
]
"""
def indent(s, n):
return "\n".join([line and (" " * n) + line or line
for line in s.split("\n")])
story = beginning
for example in test.examples:
story += step_start
story += indent(example.source, 12)
last_line = story.split("\n")[-2]
last_indent = len(last_line) - len(last_line.lstrip())
story += indent(step_end, last_indent)
story += end
if debug:
print story
coffee = subprocess.Popen(["coffee", "-s"], shell=False,
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = coffee.communicate(story)
for example in test.examples:
try:
if step_sep in out:
results = out.split(step_sep + "\n")[1:]
got = results[test.examples.index(example)]
else:
got = out
except IndexError:
got = "undefined"
if not checker.check_output(example.want, got, options):
raise doctest.DocTestFailure(test, example, got)
return func(*args)
return wrapper
return decorator
from plone.app.testing import PLONE_FIXTURE
from plone.app.testing import FunctionalTesting
from plone.testing import z2
FUNCTIONAL_TESTING = FunctionalTesting(
bases=(PLONE_FIXTURE, z2.ZSERVER_FIXTURE), name="PloneFixture:ZServer")
import unittest
class ZombieBrowserTest(unittest.TestCase):
layer = FUNCTIONAL_TESTING
@browser("http://localhost:55001/plone/")
def test_login(self):
"""
Let's start by looking up the login link.
>>> console.log do $("#personaltools-login").text
Log in
Clicking that link should not redirect us anywhere, but give us an
AJAX overlay with a login form.
>>> do ($ "#personaltools-login").click
>>> console.log window.location.href
... console.log do ($ ".pb-ajax #login-form").text
http://localhost:55001/plone/
Login Name
Password
Let's fill that form...
>>> global.form = ($ ".pb-ajax #login-form")
... form.find("#__ac_name").val "%(TEST_USER_NAME)s"
... form.find("#__ac_password").val "%(TEST_USER_PASSWORD)s"
... console.log do form.find("#__ac_name").val
... console.log do form.find("#__ac_password").val
%(TEST_USER_NAME)s
%(TEST_USER_PASSWORD)s
... and click the button to log in.
>>> do form.find("input[type='submit']").click
>>> console.log window.location.href
... console.log browser.text ".documentFirstHeading"
http://localhost:55001/plone/login_form
You are now logged in
Uh oh, we were redirected, so zombie is not a perfect browser yet.
Also, notice, that we couldn't use jQuery in testing the document first
heading (we used zombie's custom API), because the context after the
click is an AJAX-response without jQuery or any other javascript.
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment