import os, sets
from itertools import izip
from twisted.trial import unittest
from twisted.python import util
from twisted.web import microdom
from nevow import athena, rend, tags, flat, loaders
from nevow.inevow import IRequest
from nevow.context import WovenContext
from nevow.testutil import FakeRequest, renderLivePage
class _TestJSModule(athena.JSModule):
extractCounter = 0
def _extractImports(self, *a, **kw):
self.extractCounter += 1
return super(_TestJSModule, self)._extractImports(*a, **kw)
class Utilities(unittest.TestCase):
testModuleImpl = '''\
lalal this is javascript honest
// uh oh! a comment! gee I wish javascript had an import system
// import ExampleModule
here is some more javascript code
// import Another
// import Module
the end
'''
def testJavaScriptModule(self):
testModuleFilename = self.mktemp()
testModule = file(testModuleFilename, 'w')
testModule.write(self.testModuleImpl)
testModule.close()
modules = {'testmodule': testModuleFilename}
m1 = athena.JSModule.getOrCreate('testmodule', modules)
m2 = athena.JSModule.getOrCreate('testmodule', modules)
self.assertEquals(m1.name, 'testmodule')
self.assertIdentical(m1, m2)
modules['Another'] = self.mktemp()
anotherModule = file(modules['Another'], 'w')
anotherModule.write('// import SecondaryDependency\n')
anotherModule.close()
modules['ExampleModule'] = self.mktemp()
exampleModule = file(modules['ExampleModule'], 'w')
exampleModule.write('// import ExampleDependency\n')
exampleModule.close()
modules['Module'] = self.mktemp()
moduleModule = file(modules['Module'], 'w')
moduleModule.close()
# Stub these out with an empty file
modules['SecondaryDependency'] = modules['Module']
modules['ExampleDependency'] = modules['Module']
deps = [d.name for d in m1.dependencies()]
deps.sort()
self.assertEquals(deps, ['Another', 'ExampleModule', 'Module'])
depgraph = {
'Another': ['SecondaryDependency'],
'ExampleModule': ['ExampleDependency'],
'Module': [],
'testmodule': ['Another', 'ExampleModule', 'Module'],
'SecondaryDependency': [],
'ExampleDependency': []}
allDeps = [d.name for d in m1.allDependencies()]
for m in allDeps:
modDeps = depgraph[m]
for d in modDeps:
# All dependencies should be loaded before the module
# that depends upon them.
self.assertIn(d, allDeps)
self.assertIn(m, allDeps)
self.failUnless(allDeps.index(d) < allDeps.index(m))
def test_dependencyCaching(self):
"""
Test that dependency caching works as expected.
"""
testModuleFilename = self.mktemp()
testModule = file(testModuleFilename, 'w')
testModule.write('')
testModule.close()
modules = {'testmodule': testModuleFilename}
m = _TestJSModule('testmodule', modules)
deps = list(m.dependencies())
self.assertEquals(m.extractCounter, 1)
deps2 = list(m.dependencies())
self.assertEquals(m.extractCounter, 1)
newTime = m.lastModified
os.utime(testModuleFilename, (newTime + 1, newTime + 1))
deps3 = list(m.dependencies())
self.assertEquals(m.extractCounter, 2)
def test_renderJavascriptModules(self):
"""
The parent of the javascript modules is not renderable itself. Make
sure it's a 404.
"""
m = athena.JSModules({})
self.failUnless(isinstance(m.renderHTTP(None), rend.FourOhFour))
def test_lookupNonExistentJavascriptModule(self):
"""
Test that the parent resource for all JavaScript modules returns the
correct thing when asked for a module.
"""
m = athena.JSModules({'name': 'value'})
self.assertEquals(m.locateChild(None, ('key',)), rend.NotFound)
def test_lookupJavascriptModule(self):
"""
Test that retrieving a JavaScript module which actually exists returns
whatever the resourceFactory method produces.
"""
m = athena.JSModules({'name': 'value'})
m.resourceFactory = sets.Set
resource, segments = m.locateChild(None, ('name',))
self.assertEquals(segments, [])
self.assertEquals(resource, sets.Set('value'))
def testPackage(self):
baseDir = util.sibpath(__file__, 'test_package')
package = athena.AutoJSPackage(baseDir)
def _f(*sib):
return os.path.join(baseDir, *sib)
expected = {u'Foo': _f('Foo', '__init__.js'),
u'Foo.Bar': _f('Foo', 'Bar.js'),
u'Foo.Baz': util.sibpath(athena.__file__, 'empty.js'),
u'Foo.Baz.Quux': _f('Foo', 'Baz', 'Quux.js')}
for module, path in expected.iteritems():
self.assertIn(module, package.mapping)
self.assertEquals(package.mapping[module], path)
def testPackageDeps(self):
modules = {u'Foo': self.mktemp(), u'Foo.Bar': self.mktemp()}
file(modules[u'Foo'], 'wb').close()
file(modules[u'Foo.Bar'], 'wb').close()
foo = athena.JSModule.getOrCreate(u'Foo', modules)
bar = athena.JSModule.getOrCreate(u'Foo.Bar', modules)
self.assertIn(foo, bar.allDependencies())
def test_preprocessorCollection(self):
"""
Test that preprocessors from all the base classes of an instance are
found, and that a preprocessor instance attribute overrides all of
these.
"""
a, b, c = object(), object(), object()
class Base(object):
preprocessors = [a]
class OtherBase(object):
preprocessors = [b]
class Derived(Base, OtherBase):
preprocessors = [c]
inst = Derived()
self.assertEqual(
rend._getPreprocessors(inst),
[a, b, c])
d = object()
inst.preprocessors = [d]
self.assertEqual(
rend._getPreprocessors(inst),
[d])
def test_handlerMacro(self):
"""
Test that the handler macro rewrites athena:handler nodes to the
appropriate JavaScript.
"""
expectedOutput = (
'return Nevow.Athena.Widget.handleEvent('
'this, "onclick", "bar");')
tag = tags.span[athena.handler(event='onclick', handler='bar')]
mutated = athena._rewriteEventHandlerToAttribute(tag)
output = flat.flatten(mutated)
self.assertEquals(
output,
'')
def test_handlerMacroAgainstList(self):
"""
Macros need to be runnable on lists of things. Make sure the handler
macro is.
"""
tag = ["hello", " ", "world"]
self.assertEquals(
athena._rewriteEventHandlerToAttribute(tag),
tag)
def test_athenaIdRewriting(self):
"""
Test that IDs are correctly rewritten in id, for, and headers
attributes.
"""
tag = [tags.label(_for='foo'),
tags.input(id='foo'),
tags.th(headers=''),
tags.th(headers='foo'),
tags.td(headers='foo bar'),
tags.td(headers='foo bar baz')]
element = athena.LiveElement(docFactory=loaders.stan(tag))
page = athena.LivePage(docFactory=loaders.stan(element))
element.setFragmentParent(page)
def _verifyRendering(result):
self.assertIn('