1# Copyright (c) 2006 Divmod.
2# See LICENSE for details.
3
4"""
5Test the dependency tracking and javascript generation code in
6L{nevow.jsutil}.
7"""
8
9from textwrap import dedent
10from twisted.internet.utils import getProcessOutput
11from twisted.trial.unittest import TestCase
12from nevow.testutil import setJavascriptInterpreterOrSkip
13from nevow.jsutil import getDependencies, generateTestScript
14from nevow import athena
15
16class _ConsoleJSTestMixin:
17    """
18    Things that might be useful for testing JavaScript interaction functions
19    from L{nevow.testutil}.
20    """
21
22    def _getPackages(self):
23        """
24        @return: the mapping of all javascript packages plus some fake modules
25        """
26        packages = athena.allJavascriptPackages()
27        packages.update(
28            {'ConsoleJSTestFoo': self._outputToTempFile(
29                        'print("hello from ConsoleJSTestFoo");'),
30             'ConsoleJSTestFoo.Bar': self._outputToTempFile(
31                            dedent(
32                                '''
33                                // import ConsoleJSTestFoo
34                                print("hello from ConsoleJSTestFoo.Bar");
35                                ''')),
36             'ConsoleJSTestFoo.Baz': self._outputToTempFile(
37                            dedent(
38                                '''
39                                // import ConsoleJSTestFoo
40                                // import ConsoleJSTestFoo.Bar
41                                print("hello from ConsoleJSTestFoo.Baz");
42                                '''))})
43        return packages
44
45    def _outputToTempFile(self, s):
46        """
47        Write the contents of string C{s} to a tempfile and return the
48        filename that was used
49
50        @param s: file contents
51        @type s: C{str}
52
53        @return: filename
54        @rtype: C{str}
55        """
56        fname = self.mktemp()
57        fObj = file(fname, 'w')
58        fObj.write(s)
59        fObj.close()
60        return fname
61
62class DependenciesTestCase(TestCase, _ConsoleJSTestMixin):
63    """
64    Tests for L{getDependencies}
65    """
66    def test_getDependenciesNoModules(self):
67        """
68        Test that L{getDependencies} returns the empty list when the js module
69        it's passed doesn't explicitly import anything and the C{bootstrap} and
70        C{ignore} parameters are empty
71        """
72        deps = getDependencies(
73                self._outputToTempFile(''), ignore=(), bootstrap=())
74        self.assertEqual(len(deps), 0)
75
76
77    def test_getDependenciesBootstrap(self):
78        """
79        Test that L{getDependencies} returns a list containing only the
80        bootstrap modules when the js module it's passed doesn't explicitly
81        import anything and the "ignore" parameter is empty.
82        """
83        bootstrap = ['ConsoleJSTestFoo.Bar', 'ConsoleJSTestFoo.Baz']
84
85        deps = getDependencies(
86                self._outputToTempFile(''),
87                ignore=(),
88                bootstrap=bootstrap,
89                packages=self._getPackages())
90        self.assertEqual([d.name for d in deps], bootstrap)
91
92
93    def test_getDependenciesIgnore(self):
94        """
95        Test that L{getDependencies} observes the C{ignore} parameter
96        """
97        deps = getDependencies(
98                self._outputToTempFile(
99                    dedent(
100                        '''
101                        // import ConsoleJSTestFoo.Bar
102                        // import ConsoleJSTestFoo.Baz
103                        ''')),
104                ignore=('ConsoleJSTestFoo.Bar',),
105                bootstrap=(),
106                packages=self._getPackages())
107
108        self.assertEqual([d.name for d in deps], ['ConsoleJSTestFoo', 'ConsoleJSTestFoo.Baz'])
109
110    def test_getDependenciesAll(self):
111        """
112        Test that L{getDependencies} works if we import a single module which
113        in turn depends on multiple modules
114        """
115        fname = self._outputToTempFile(
116            '// import ConsoleJSTestFoo.Baz')
117
118        deps = getDependencies(
119                fname,
120                ignore=(),
121                bootstrap=(),
122                packages=self._getPackages())
123
124        self.assertEqual([d.name for d in deps], ['ConsoleJSTestFoo', 'ConsoleJSTestFoo.Bar', 'ConsoleJSTestFoo.Baz'])
125
126
127
128class JSGenerationTestCase(TestCase, _ConsoleJSTestMixin):
129    """
130    Tests for L{generateTestScript}
131    """
132    javascriptInterpreter = None
133
134    def test_generateTestScript(self):
135        """
136        Test for L{generateTestScript}
137        """
138        fname = self._outputToTempFile(
139                    dedent(
140                        '''
141                        // import ConsoleJSTestFoo.Bar
142                        // import ConsoleJSTestFoo.Baz
143                        print("hello from the test module");
144                        '''))
145
146        deps = getDependencies(
147                fname,
148                ignore=(),
149                bootstrap=(),
150                packages=self._getPackages())
151
152        script = generateTestScript(
153                    fname,
154                    dependencies=deps)
155
156        scriptfname = self._outputToTempFile(script)
157
158        def gotResult(s):
159            self.assertEqual(s.split('\n'),
160                             ['hello from ConsoleJSTestFoo',
161                              'hello from ConsoleJSTestFoo.Bar',
162                              'hello from ConsoleJSTestFoo.Baz',
163                              'hello from the test module',
164                              ''])
165
166        result = getProcessOutput(self.javascriptInterpreter, ('-f', scriptfname))
167        result.addCallback(gotResult)
168        return result
169
170setJavascriptInterpreterOrSkip(JSGenerationTestCase)
171