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('