1# Copyright (c) 2004 Divmod.
2# See LICENSE for details.
3
4
5from nevow import tags, flat, testutil, context, loaders, stan
6
7from nevow.inevow import IQ
8
9
10simple = tags.html[tags.div(pattern="foo")]
11tooMany = tags.html[tags.div(pattern="foo"), tags.div(pattern="foo")]
12notEnough = tags.html[tags.div[tags.span["Hello"]]]
13
14
15class OnePatternTestCase(testutil.TestCase):
16    """
17    Test various C{IQ.onePattern} implementations.
18    """
19    _patternDiv = tags.div(pattern="foo")
20
21    _simpleStan = tags.html[_patternDiv]
22
23    _simpleSlot = tags.slot('slotname')[_patternDiv]
24
25    _tooManyPatternsSiblingStan = tags.html[
26        tags.div(pattern="foo"),
27        tags.div(pattern="foo")]
28
29    _manyPatternsLinealStan = tags.html(pattern="foo")[
30        tags.div(pattern="foo"),
31        "extra content"]
32
33
34    def _testQuery(self, container, expected):
35        pattern = IQ(container).onePattern('foo')
36
37        # The pattern node has had its pattern special removed - put it back,
38        # so we can perform a comparison
39        self.assertEqual(pattern.pattern, None)
40        pattern.pattern = 'foo'
41
42        self.assertEqual(str(pattern), str(expected))
43
44
45    def test_tagQuery(self):
46        return self._testQuery(
47            self._simpleStan, self._patternDiv)
48
49
50    def test_contextQuery(self):
51        return self._testQuery(
52            context.WovenContext(tag=self._simpleStan),
53            self._patternDiv)
54
55
56    def test_listQuery(self):
57        return self._testQuery(
58            flat.precompile(self._simpleStan),
59            self._patternDiv)
60
61
62    def test_loaderQuery(self):
63        return self._testQuery(
64            loaders.stan(self._simpleStan),
65            self._patternDiv)
66
67
68    def test_slotQuery(self):
69        return self._testQuery(
70            self._simpleSlot,
71            self._patternDiv)
72
73
74    def test_precompiledSlotQuery(self):
75        return self._testQuery(
76            flat.precompile(self._simpleSlot),
77            self._patternDiv)
78
79
80    def _testTooManyPatterns(self, obj):
81        """
82        Test that the L{IQ} adapter for C{obj} provides a L{onePattern} method
83        which raises L{stan.TooManyNodes} if passed a pattern name for which
84        there are multiple pattern nodes.
85        """
86        self.assertRaises(stan.TooManyNodes, IQ(obj).onePattern, 'foo')
87
88
89    def test_stanTooManySiblingPatterns(self):
90        """
91        Test that a Tag with children with the same pattern name causes
92        onePattern to raise L{TooManyNodes}.
93        """
94        return self._testTooManyPatterns(self._tooManyPatternsSiblingStan)
95
96
97    def test_contextTooManySiblingPatterns(self):
98        """
99        Like L{test_stanTooManySiblingPatterns} but for a WovenContext.
100        """
101        return self._testTooManyPatterns(
102            context.WovenContext(tag=self._tooManyPatternsSiblingStan))
103
104
105    def test_listTooManySiblingPatterns(self):
106        """
107        Like L{test_stanTooManySiblingPatterns} but for a list.
108        """
109        return self._testTooManyPatterns([self._tooManyPatternsSiblingStan])
110
111
112    def test_precompiledTooManySiblingPatterns(self):
113        """
114        Like L{test_stanTooManySiblingPatterns} but for a precompiled document.
115        """
116        P = flat.precompile(self._tooManyPatternsSiblingStan)
117        return self._testTooManyPatterns(P)
118
119
120    def test_loaderTooManySiblingPatterns(self):
121        """
122        Like L{test_stanTooManySiblingPatterns} but for a loader.
123        """
124        return self._testTooManyPatterns(loaders.stan(self._tooManyPatternsSiblingStan))
125
126
127    def test_stanMultipleLinealPatterns(self):
128        """
129        Test that calling onePattern a Tag with a pattern and a child with the
130        same pattern
131        """
132        return self._testQuery(
133            self._manyPatternsLinealStan,
134            self._manyPatternsLinealStan)
135
136
137    def test_contextMultipleLinealPatterns(self):
138        return self._testQuery(
139            context.WovenContext(tag=self._manyPatternsLinealStan),
140            self._manyPatternsLinealStan)
141
142
143    def test_listMultipleLinealPatterns(self):
144        return self._testQuery(
145            [self._manyPatternsLinealStan],
146            self._manyPatternsLinealStan)
147
148
149    def test_precompiledMultipleLinealPatterns(self):
150        P = flat.precompile(self._manyPatternsLinealStan)
151        return self._testQuery(
152            P,
153            P[0].tag)
154
155
156    def test_loaderMultipleLinealPatterns(self):
157        return self._testQuery(
158            loaders.stan(self._manyPatternsLinealStan),
159            loaders.stan(self._manyPatternsLinealStan).load()[0].tag)
160
161
162    def test_tagNotEnough(self):
163        self.assertRaises(stan.NodeNotFound, IQ(notEnough).onePattern, 'foo')
164
165    def test_contextNotEnough(self):
166        self.assertRaises(
167            stan.NodeNotFound,
168            IQ(context.WovenContext(tag=notEnough)).onePattern, 'foo')
169
170    def test_contextTagQuery(self):
171        T = simple.clone(deep=False)
172        T.pattern = "outer"
173        C = context.WovenContext(tag=T)
174        new = IQ(C).onePattern('outer')
175        self.assertEquals(new.tagName, 'html')
176
177    def test_listNotEnough(self):
178        P = flat.precompile(notEnough)
179        self.assertRaises(stan.NodeNotFound, IQ(P).onePattern, 'foo')
180
181    def test_loaderNotEnough(self):
182        L = loaders.stan(notEnough)
183        self.assertRaises(stan.NodeNotFound, IQ(L).onePattern, 'foo')
184
185
186multiple = tags.html[tags.div(pattern="foo", bar="one"), tags.span(pattern="foo", bar="two")]
187
188
189class TestAll(testutil.TestCase):
190    def verify(self, them):
191        them = list(them)
192        self.assertEquals(len(them), 2)
193        self.assertEquals(them[0].tagName, 'div')
194        self.assertEquals(them[1].tagName, 'span')
195        self.assertEquals(them[0].attributes['bar'], 'one')
196        self.assertEquals(them[1].attributes['bar'], 'two')
197
198    def testTagPatterns(self):
199        self.verify(
200            IQ(multiple).allPatterns('foo'))
201
202    def testContextPatterns(self):
203        self.verify(
204            IQ(context.WovenContext(tag=multiple)).allPatterns('foo'))
205
206    def testListPatterns(self):
207        self.verify(
208            IQ(flat.precompile(multiple)).allPatterns('foo'))
209
210    def testLoaderPatterns(self):
211        self.verify(
212            IQ(loaders.stan(multiple)).allPatterns('foo'))
213
214
215class TestGenerator(testutil.TestCase):
216    def verify(self, it):
217        one = it(color="red")
218        two = it(color="blue")
219        three = it(color="green")
220        four = it(color="orange")
221        self.assertEquals(one.attributes['color'], 'red')
222        self.assertEquals(one.attributes['bar'], 'one')
223        self.assertEquals(two.attributes['color'], 'blue')
224        self.assertEquals(two.attributes['bar'], 'two')
225        self.assertEquals(three.attributes['color'], 'green')
226        self.assertEquals(three.attributes['bar'], 'one')
227        self.assertEquals(four.attributes['color'], 'orange')
228        self.assertEquals(four.attributes['bar'], 'two')
229
230    def testTagGenerators(self):
231        self.verify(
232            IQ(multiple).patternGenerator('foo'))
233
234    def testTagMissing(self):
235        self.assertRaises(stan.NodeNotFound, IQ(notEnough).patternGenerator, 'foo')
236
237    def testContextGenerators(self):
238        self.verify(
239            IQ(context.WovenContext(tag=multiple)).patternGenerator('foo'))
240
241    def testContextMissing(self):
242        self.assertRaises(stan.NodeNotFound, IQ(context.WovenContext(tag=notEnough)).patternGenerator, 'foo')
243
244    def testListGenerators(self):
245        self.verify(
246            IQ(flat.precompile(multiple)).patternGenerator('foo'))
247
248    def testListMissing(self):
249        self.assertRaises(stan.NodeNotFound, IQ(flat.precompile(notEnough)).patternGenerator, 'foo')
250
251    def testLoaderGenerators(self):
252        self.verify(
253            IQ(loaders.stan(multiple)).patternGenerator('foo'))
254
255    def testTagMissing(self):
256        self.assertRaises(stan.NodeNotFound, IQ(loaders.stan(notEnough)).patternGenerator, 'foo')
257
258    def testClonableDefault(self):
259        orig = tags.p["Hello"]
260        gen = IQ(flat.precompile(notEnough)).patternGenerator('foo', orig)
261        new = gen.next()
262        self.assertEquals(new.tagName, 'p')
263        self.assertNotIdentical(orig, new)
264
265    def testNonClonableDefault(self):
266        gen = IQ(flat.precompile(notEnough)).patternGenerator('foo', 'bar')
267        new = gen.next()
268        self.assertEquals(new, 'bar')
269
270    def testXmlMissing(self):
271        self.assertRaises(stan.NodeNotFound, IQ(stan.xml('<html>hello</html>')).patternGenerator, 'foo')
272
273
274    def test_listOfTagPatternGenerator(self):
275        """
276        Querying a list which contains a tag for patterns gives back the tag if
277        the tag has a matching pattern special.
278        """
279        patterns = IQ([tags.div(pattern="foo", bar="baz")]).patternGenerator("foo")
280        for i in xrange(3):
281            self.assertEqual(patterns.next().attributes['bar'], "baz")
282