source: products/quintagroup.transmogrifier/branches/plone-2.1/quintagroup.transmogrifier/quintagroup/transmogrifier/tests.py @ 710

Last change on this file since 710 was 710, checked in by mylan, 17 years ago

Create 2.5.2 version tag.

File size: 30.2 KB
Line 
1import unittest
2import pprint
3import os
4
5import collective.transmogrifier.zopex3
6
7from zope.interface import Interface, classProvides, implements
8from zope.component import provideUtility, provideAdapter, adapts
9
10from zope.testing import doctest, cleanup
11
12from collective.transmogrifier.interfaces import ISectionBlueprint, ISection
13from collective.transmogrifier.tests import tearDown
14from collective.transmogrifier.sections.tests import sectionsSetUp
15from collective.transmogrifier.sections.tests import SampleSource
16
17from Products.Five import zcml
18
19import quintagroup.transmogrifier
20from quintagroup.transmogrifier.xslt import stylesheet_registry
21
22# Doctest support
23
24class DataPrinter(object):
25    classProvides(ISectionBlueprint)
26    implements(ISection)
27
28    def __init__(self, transmogrifier, name, options, previous):
29        self.previous = previous
30        self.printkey = [i.strip() for i in options['print'].splitlines() if i.strip()]
31        if 'prettyprint' in options:
32            self.pprint = pprint.PrettyPrinter().pprint
33
34    def __iter__(self):
35        for item in self.previous:
36            if self.printkey:
37                data = item
38                for i in self.printkey:
39                    if i in data:
40                        data = data[i]
41                    else:
42                        data = None
43                        break
44                if data is not None:
45                    if hasattr(self, 'pprint'):
46                        self.pprint(data)
47                    else:
48                        print data
49            yield item
50
51ctSectionsSetup = sectionsSetUp
52def sectionsSetUp(test):
53    ctSectionsSetup(test)
54    import zope.app.annotation
55    zcml.load_config('configure.zcml', zope.app.annotation)
56    zcml.load_config('configure.zcml', quintagroup.transmogrifier)
57
58    from Products.CMFCore import utils
59    def getToolByName(context, tool_id):
60        return context
61    utils.getToolByName = getToolByName
62
63    import Acquisition
64    def aq_base(obj):
65        return obj
66    Acquisition.aq_base = aq_base
67
68    provideUtility(DataPrinter,
69        name=u'quintagroup.transmogrifier.tests.dataprinter')
70
71def siteWalkerSetUp(test):
72    sectionsSetUp(test)
73
74    from collective.transmogrifier.interfaces import IFolderish
75    from quintagroup.transmogrifier.interfaces import IBaseFolder
76
77    class MockContent(object):
78        path = ()
79
80        def getPhysicalPath(self):
81            return self.path
82
83        def getPortalTypeName(self):
84            return self.__class__.__name__
85
86    class Document(MockContent):
87        pass
88
89    class File(MockContent):
90        pass
91
92    class Folder(MockContent, dict):
93        implements(IBaseFolder)
94
95        contentItems = dict.items
96        contentValues = dict.values
97
98    class MockPortal(MockContent, dict):
99        implements(IFolderish)
100
101        contentItems = dict.items
102        contentValues = dict.values
103
104    portal = MockPortal()
105
106    test.globs['plone'] = portal
107    test.globs['transmogrifier'].context = test.globs['plone']
108
109    portal.path = ('', 'plone')
110    portal['document1'] = Document()
111    portal['document1'].path = ('', 'plone', 'document1')
112    portal['folder1'] = Folder()
113    portal['folder1'].path = ('', 'plone', 'folder1')
114    portal['folder1']['document2'] = Document()
115    portal['folder1']['document2'].path = ('', 'plone', 'folder1', 'document2')
116    portal['folder1']['folder2'] = Folder()
117    portal['folder1']['folder2'].path = ('', 'plone', 'folder1', 'folder2')
118    portal['folder1']['folder2']['file'] = File()
119    portal['folder1']['folder2']['file'].path  = ('', 'plone', 'folder1', 'folder2', 'file')
120    portal['document3'] = Document()
121    portal['document3'].path = ('', 'plone', 'document3')
122    portal['file'] = File()
123    portal['file'].path = ('', 'plone', 'file')
124
125def manifestSetUp(test):
126    sectionsSetUp(test)
127
128    root = dict(
129        _path='',
130        _entries=(
131            ('news', 'Folder'),
132            ('events', 'Folder'),
133            ('front-page', 'Document'),
134            ('only-in-manifest', 'Document')
135        )
136    )
137
138    news = dict(
139        _path='news',
140        _entries=(
141            ('aggregator', 'Topic'),
142            ('once-more', 'File')
143        )
144    )
145
146    aggregator = dict(
147        _path='news/aggregator',
148    )
149
150    events = dict(
151        _path='events'
152    )
153
154    front_page = dict(
155        _path='front-page',
156    )
157
158    members = dict(
159        _path='Members'
160    )
161
162    class ManifestSource(SampleSource):
163        classProvides(ISectionBlueprint)
164        implements(ISection)
165
166        def __init__(self, *args, **kw):
167            super(ManifestSource, self).__init__(*args, **kw)
168            self.sample = (root, dict(), news, aggregator, events, front_page, members)
169
170    provideUtility(ManifestSource,
171        name=u'quintagroup.transmogrifier.tests.manifestsource')
172
173def marshallSetUp(test):
174    sectionsSetUp(test)
175
176    from plone.app.transmogrifier.interfaces import IBaseObject
177
178    class Field(object):
179        def __init__(self, name):
180            self.name = name
181            self.obj = None
182
183        def getAccessor(self, obj):
184            self.obj = obj
185            return self
186
187        def getMutator(self, obj):
188            self.obj = obj
189            return self
190
191        def __call__(self, value=None):
192            if value is None:
193                return self.obj.fields[self.name]
194            else:
195                self.obj.fields[self.name] = value
196
197    class MockBase(object):
198        def __init__(self, effective=None):
199            self.fields = {
200                'effectiveDate': effective,
201                'modification_date': 'changed',
202            }
203
204        def checkCreationFlag(self):
205            return True
206
207        def unmarkCreationFlag(self):
208            pass
209
210        def at_post_create_script(self):
211            pass
212
213        def at_post_edit_script(self):
214            pass
215
216        indexed = ()
217        def indexObject(self):
218            self.indexed += (self._last_path,)
219
220        def getField(self, fname):
221            return Field(fname)
222
223    class MockCriterion(MockBase):
224        implements(IBaseObject)
225        _last_path = None
226
227        def indexObject(self):
228            self.indexed += (self._last_path,)
229
230    class MockPortal(MockBase):
231        implements(IBaseObject)
232
233        criterion = MockCriterion('not changed')
234
235        _last_path = None
236        def unrestrictedTraverse(self, path, default):
237            if path[0] == '/':
238                return default # path is absolute
239            if isinstance(path, unicode):
240                return default
241            if path == 'not/existing/bar':
242                return default
243            if path == 'topic/criterion':
244                self._last_path = path
245                self.criterion._last_path = path
246                return self.criterion
247            if path.endswith('/notatcontent'):
248                return object()
249            self._last_path = path
250            return self
251
252        def getId(self):
253            return "plone"
254
255        updatedRoles = False
256        def updateRoleMappings(self):
257            self.updatedRoles = True
258
259        reindexed = False
260        def reindexIndex(self, name, extra=None):
261            self.reindexed = True
262
263        marshalled = ()
264        def marshall(self, instance, **kwargs):
265            self.marshalled += ((self._last_path, kwargs.get('atns_exclude')),)
266            # Marshall often fails to export topic criteria
267            if isinstance(instance, MockCriterion):
268                return None, None, None
269            else:
270                return None, None, "marshalled"
271
272        demarshalled = ()
273        def demarshall(self, instance, data):
274            # we don't need to test Marshall product, only check if we call it's components
275            self.demarshalled += (self._last_path,)
276
277    portal = MockPortal()
278    test.globs['plone'] = portal
279    test.globs['transmogrifier'].context = test.globs['plone']
280
281    from Products.Marshall import registry
282    def getComponent(name):
283        return portal
284    registry.getComponent = getComponent
285
286    class MarshallSource(SampleSource):
287        classProvides(ISectionBlueprint)
288        implements(ISection)
289
290        def __init__(self, *args, **kw):
291            super(MarshallSource, self).__init__(*args, **kw)
292            self.sample = (
293                dict(),
294                dict(_path='spam/eggs/foo', _excluded_fields=('file', 'image')),
295                dict(_path='topic/criterion'),
296                dict(_path='not/existing/bar'),
297                dict(_path='spam/eggs/notatcontent', 
298                     _files=dict(marshall=dict(data='xml', name='.marshall.xml'))),
299            )
300    provideUtility(MarshallSource,
301        name=u'quintagroup.transmogrifier.tests.marshallsource')
302
303def propertyManagerSetUp(test):
304    sectionsSetUp(test)
305
306    from interfaces import IPropertyManager
307
308    class MockPortal(object):
309        implements(IPropertyManager)
310
311        _properties = (
312            {'id':'title', 'type': 'string', 'mode': 'w'},
313            {'id':'description', 'type': 'string', 'mode': 'w'},
314            {'id':'encoding', 'type': 'string', 'mode': 'w'},
315            {'id':'author', 'type': 'string', 'mode': 'w'}
316        )
317
318        _last_path = None
319        def unrestrictedTraverse(self, path, default):
320            if path[0] == '/':
321                return default # path is absolute
322            if isinstance(path, unicode):
323                return default
324            if path == 'not/existing/bar':
325                return default
326            if path.endswith('/notatcontent'):
327                return object()
328            self._last_path = path
329            return self
330
331        def _propertyMap(self):
332            return self._properties
333
334        def getProperty(self, id, d=None):
335            return 'value'
336
337        def propdict(self):
338            d={}
339            for p in self._properties:
340                d[p['id']]=p
341            return d
342
343        updated = ()
344        def _updateProperty(self, id, value):
345            self.updated += ((self._last_path, id, value))
346
347    portal = MockPortal()
348    test.globs['plone'] = portal
349    test.globs['transmogrifier'].context = test.globs['plone']
350
351    class PropertyManagerSource(SampleSource):
352        classProvides(ISectionBlueprint)
353        implements(ISection)
354
355        def __init__(self, *args, **kw):
356            super(PropertyManagerSource, self).__init__(*args, **kw)
357            self.sample = (
358                dict(),
359                dict(_path='not/existing/bar'),
360                dict(_path='spam/eggs/notatcontent'),
361                dict(_path='spam/eggs/foo', _excluded_properties=('encoding',)),
362            )
363
364    provideUtility(PropertyManagerSource,
365        name=u'quintagroup.transmogrifier.tests.propertymanagersource')
366
367def commentsSetUp(test):
368    sectionsSetUp(test)
369
370    class MockDiscussionItem(object):
371        creator = 'creator'
372        modified = 'date'
373
374        def __init__(self, reply, text=""):
375            self.in_reply_to = reply
376            self.text = text
377
378        def __of__(self, container):
379            return self
380
381        def getMetadataHeaders(self):
382            return []
383
384        def setMetadata(self, headers):
385            pass
386
387        def Creator(self):
388            return self.creator
389
390        def addCreator(self, creator):
391            self.creator = creator
392
393        def ModificationDate(self):
394            return self.modified
395
396        def setModificationDate(self, date):
397            self.modified = date
398
399        def setFormat(self, format):
400            pass
401
402        def _edit(self, text=None):
403            self.text = text
404
405        def indexObject(self):
406            pass
407
408        def __repr__(self):
409            return "<DicussionItem %s %s %s %s>" % (
410                self.Creator(),
411                self.ModificationDate(),
412                self.in_reply_to,
413                self.text
414                )
415
416    from Products.CMFDefault import DiscussionItem
417    DiscussionItem.DiscussionItem = MockDiscussionItem
418
419    class MockPortal(object):
420        _discussion = {
421            '1': MockDiscussionItem(None, 'comment to content'),
422            '2': MockDiscussionItem('1', 'reply to first comment'),
423            '3': MockDiscussionItem(None, 'other comment to content')
424        }
425        _container = {}
426
427        @property
428        def talkback(self):
429            return self
430
431        def objectItems(self):
432            l = self._discussion.items()
433            l.sort(key=lambda x: int(x[0]))
434            return l
435
436        def unrestrictedTraverse(self, path, default):
437            if path[0] == '/':
438                return default # path is absolute
439            if isinstance(path, unicode):
440                return default
441            if path == 'not/existing/bar':
442                return default
443            if path.endswith('/notdiscussable'):
444                return object()
445            return self
446
447        def getDiscussionFor(self, obj):
448            return self
449
450    portal = MockPortal()
451    test.globs['plone'] = portal
452    test.globs['transmogrifier'].context = test.globs['plone']
453
454    class CommentsSource(SampleSource):
455        classProvides(ISectionBlueprint)
456        implements(ISection)
457
458        def __init__(self, *args, **kw):
459            super(CommentsSource, self).__init__(*args, **kw)
460            self.sample = (
461                dict(),
462                dict(_path='not/existing/bar'),
463                dict(_path='spam/eggs/notdiscussable'),
464                dict(_path='spam/eggs/foo'),
465            )
466
467    provideUtility(CommentsSource,
468        name=u'quintagroup.transmogrifier.tests.commentssource')
469
470
471def dataCorrectorSetUp(test):
472    sectionsSetUp(test)
473
474    class IPortal(Interface):
475        pass
476
477    class MockPortal(object):
478        implements(IPortal)
479
480        def unrestrictedTraverse(self, path, default):
481            if path[0] == '/':
482                return default # path is absolute
483            if isinstance(path, unicode):
484                return default
485            if path == 'not/existing/bar':
486                return default
487            if path.endswith('/notadaptable'):
488                return object()
489            return self
490
491    portal = MockPortal()
492    test.globs['plone'] = portal
493    test.globs['transmogrifier'].context = test.globs['plone']
494
495    from quintagroup.transmogrifier.interfaces import IExportDataCorrector, \
496        IImportDataCorrector
497
498    class MockExportAdapter(object):
499        #implements(IExportDataCorrector)
500        #adapts(MockPortal)
501        def __init__(self, context):
502            self.context = context
503
504        def __call__(self, data):
505            return "modified export data"
506
507    provideAdapter(MockExportAdapter, (IPortal,), IExportDataCorrector, name="marshall")
508
509    class MockImportAdapter(object):
510        #implements(IImportDataCorrector)
511        #adapts(MockPortal)
512        def __init__(self, context):
513            self.context = context
514
515        def __call__(self, data):
516            return "modified import data"
517
518    provideAdapter(MockImportAdapter, (IPortal,), IImportDataCorrector, name="manifest")
519
520    class DataCorrectorSource(SampleSource):
521        classProvides(ISectionBlueprint)
522        implements(ISection)
523
524        def __init__(self, *args, **kw):
525            super(DataCorrectorSource, self).__init__(*args, **kw)
526            self.sample = (
527                dict(),
528                dict(_files=dict(marshall="item hasn't path")),
529                dict(_path='spam/eggs/foo'),
530                dict(_path='not/existing/bar'),
531                dict(_path='spam/eggs/notadaptable', _files=dict(marshall="object isn't adaptable")),
532                dict(_path='spam/eggs/foo',
533                     _files=dict(marshall='marshall data', unchanged='this must be unchanged')),
534                dict(_path='spam/eggs/foo',
535                     _files=dict(manifest='manifest data', unchanged='this must be unchanged')),
536            )
537
538    provideUtility(DataCorrectorSource,
539        name=u'quintagroup.transmogrifier.tests.datacorrectorsource')
540
541def writerSetUp(test):
542    sectionsSetUp(test)
543
544    class MockExportContext(object):
545        def __init__( self, *args, **kwargs):
546            self.args = args
547            for k, v in kwargs.items():
548                setattr(self, k, v)
549            self._wrote = []
550
551        def __getitem__(self, name):
552            return getattr(self, name, None)
553
554        def __contains__(self, name):
555            return hasattr(self, name)
556
557        def writeDataFile(self, filename, text, content_type, subdir=None):
558            filename = '%s/%s' % (subdir, filename)
559            self._wrote.append((filename, text, content_type))
560
561        def __repr__(self):
562            s = " ".join(["%s=%s" % (k,v) for k,v in self.__dict__.items()])
563            return "<%s %s>" % (self.__class__.__name__, s)
564
565
566    try:
567        from Products.GenericSetup import context
568    except ImportError:
569        from Products.CMFSetup import context
570
571    context.DirectoryExportContext = type('Directory', (MockExportContext,), {})
572    context.TarballExportContext = type('Tarball', (MockExportContext,), {})
573    context.SnapshotExportContext = type('Snapshot', (MockExportContext,), {})
574
575    class WriterSource(SampleSource):
576        classProvides(ISectionBlueprint)
577        implements(ISection)
578
579        def __init__(self, *args, **kw):
580            super(WriterSource, self).__init__(*args, **kw)
581            self.sample = (
582                dict(_path='spam/eggs/foo'),
583                dict(_files=dict(mock=dict(name='.first.xml', data='some data'))),
584                dict(_path='spam/eggs/foo',
585                     _files=dict(mock=dict(name='.first.xml', data='some data'),
586                                 other=dict(name='.second.xml', data='other data'))),
587                dict(_path='other/path',
588                     _files=dict(mock=dict(name='.third.xml', data='some data')))
589            )
590
591    provideUtility(WriterSource,
592        name=u'quintagroup.transmogrifier.tests.writersource')
593
594    class SingleItemSource(SampleSource):
595        classProvides(ISectionBlueprint)
596        implements(ISection)
597
598        def __init__(self, *args, **kw):
599            super(SingleItemSource, self).__init__(*args, **kw)
600            self.sample = (
601                dict(_path='', _files={}),
602            )
603
604    provideUtility(SingleItemSource,
605        name=u"quintagroup.transmogrifier.tests.singleitemsource")
606
607def readerSetUp(test):
608    sectionsSetUp(test)
609
610    class MockImportContext(object):
611
612        _dirs = [
613            'structure',
614            'structure/news', 'structure/news/recent',
615            'structure/pages', 'structure/pages/front-page',
616        ]
617        _files = [
618            'structure/.properties.xml',
619            'structure/other.file',
620            'structure/news/.objects.xml',
621            'structure/pages/.objects.xml',
622            'structure/pages/front-page/.marshall.xml',
623            'structure/pages/front-page/.comments.xml',
624        ]
625
626        def __init__( self, *args, **kwargs):
627            self.args = args
628            for k, v in kwargs.items():
629                setattr(self, k, v)
630
631        def __repr__(self):
632            s = " ".join(["%s=%s" % (k,v) for k,v in self.__dict__.items()])
633            return "<%s %s>" % (self.__class__.__name__, s)
634
635        def readDataFile(self, filename, subdir=None):
636            return 'some data'
637
638        def isDirectory(self, path):
639            return path == '' or path in self._dirs
640
641        def listDirectory(self, path):
642            all_names = self._dirs + self._files
643            if path:
644                pfx_len = len(path)+1
645            else:
646                pfx_len = 0
647            names = []
648            for name in all_names:
649                if name == path:
650                    continue
651                if not name.startswith(path):
652                    continue
653                name = name[pfx_len:]
654                if '/' in name:
655                    continue
656                names.append(name)
657            return names
658
659    try:
660        from Products.GenericSetup import context
661    except ImportError:
662        from Products.CMFSetup import context
663
664    context.DirectoryImportContext = type('Directory', (MockImportContext,),
665        {'listDirectory': lambda self, path: []})
666    context.TarballImportContext = type('Tarball', (MockImportContext,), {})
667    context.SnapshotImportContext = type('Snapshot', (MockImportContext,),
668        {'listDirectory': lambda self, path: []})
669
670def substitutionSetUp(test):
671    sectionsSetUp(test)
672
673    class SubstitutionSource(SampleSource):
674        classProvides(ISectionBlueprint)
675        implements(ISection)
676
677        def __init__(self, *args, **kw):
678            super(SubstitutionSource, self).__init__(*args, **kw)
679            self.sample = (
680                {},
681                {'_type': 'Blog'},
682                {'_type': 'PloneFormMailer'},
683                {'_type': 'Document'},
684            )
685
686    provideUtility(SubstitutionSource,
687        name=u'quintagroup.transmogrifier.tests.substitutionsource')
688
689class MetaDirectivesTests(unittest.TestCase):
690    def setUp(self):
691        zcml.load_config('meta.zcml', quintagroup.transmogrifier)
692
693    def tearDown(self):
694        stylesheet_registry.clear()
695        #cleanup.cleanUp()
696
697    def testEmptyZCML(self):
698        zcml.load_string('''\
699<configure xmlns:transmogrifier="http://namespaces.plone.org/transmogrifier">
700</configure>''')
701        self.assertEqual(stylesheet_registry.listStylesheetNames(), ())
702
703    def testConfigZCML(self):
704        zcml.load_string('''\
705<configure
706    xmlns:transmogrifier="http://namespaces.plone.org/transmogrifier">
707<transmogrifier:stylesheet
708    source="marshall"
709    from="Blog"
710    to="Weblog"
711    file="blog.xsl"
712    />
713</configure>''')
714        self.assertEqual(stylesheet_registry.listStylesheetNames(),
715                         (u'marshall:Blog:Weblog',))
716        path = os.path.split(quintagroup.transmogrifier.__file__)[0]
717        self.assertEqual(
718            stylesheet_registry.getStylesheet('marshall', 'Blog', 'Weblog'),
719            dict(from_=u'Blog',
720                 to=u'Weblog',
721                 file=os.path.join(path, 'blog.xsl'))
722        )
723
724    def testMultipleZCML(self):
725        zcml.load_string('''\
726<configure
727    xmlns:transmogrifier="http://namespaces.plone.org/transmogrifier">
728<transmogrifier:stylesheet
729    source="marshall"
730    from="Blog"
731    to="Weblog"
732    file="blog.xsl"
733    />
734<transmogrifier:stylesheet
735    source="propertymanager"
736    from="BlogEntry"
737    to="WeblogEntry"
738    file="blogentry.xsl"
739    />
740</configure>''')
741        self.assertEqual(stylesheet_registry.listStylesheetNames(),
742                         (u'marshall:Blog:Weblog', u'propertymanager:BlogEntry:WeblogEntry'))
743
744def xsltSetUp(test):
745    sectionsSetUp(test)
746
747    class XSLTSource(SampleSource):
748        classProvides(ISectionBlueprint)
749        implements(ISection)
750
751        def __init__(self, *args, **kw):
752            super(XSLTSource, self).__init__(*args, **kw)
753            self.sample = (
754                {},
755                {'_type': 'Weblog'},
756                {'_old_type': 'Blog'},
757                {'_old_type': 'Blog',
758                 '_type': 'Weblog',
759                 '_files': {'manifest': {'data': 'xml', 'name': 'manifest.xml'}}},
760                {'_old_type': 'Blog',
761                 '_type': 'Weblog',
762                 '_files': {'marshall': {'data': 'xml', 'name': 'marshall.xml'}}},
763            )
764
765    provideUtility(XSLTSource,
766        name=u'quintagroup.transmogrifier.tests.xsltsource')
767
768    from quintagroup.transmogrifier.xslt import XSLTSection, stylesheet_registry
769
770    XSLTSection.applyTransformations = lambda self, xml, xslt: 'transformed xml'
771    test.globs['stylesheet_registry'] = stylesheet_registry
772
773def binarySetUp(test):
774    sectionsSetUp(test)
775
776    from plone.app.transmogrifier.interfaces import IBaseObject
777
778    class MockPortal(object):
779        implements(IBaseObject)
780
781        _last_path = None
782        def unrestrictedTraverse(self, path, default):
783            if path[0] == '/':
784                return default # path is absolute
785            if isinstance(path, unicode):
786                return default
787            if path == 'not/existing/bar':
788                return default
789            if path.endswith('/notatcontent'):
790                return object()
791            self._last_path = path
792            return self
793
794        fields = ['id', 'title', 'file', 'image']
795
796        def Schema(self):
797            return dict.fromkeys(self.fields)
798
799        def isBinary(self, field):
800            return field in ('file', 'image')
801
802        _current_field = None
803        def getField(self, field):
804            self._current_field = field
805            return self
806
807        def getBaseUnit(self, obj):
808            return self
809
810        def getFilename(self):
811            if self._current_field == 'file':
812                return 'archive.tar.gz'
813            else:
814                return ''
815
816        def getContentType(self):
817            if self._current_field == 'file':
818                return 'application/x-tar'
819            else:
820                return 'image/png'
821
822        def getRaw(self):
823            if self._current_field == 'file':
824                return 'binary data'
825            else:
826                return ''
827
828        def getMutator(self, obj):
829            return self
830
831        updated = ()
832        def __call__(self, data, filename=None, mimetype=None):
833            self.updated += (filename, mimetype, data)
834
835    portal = MockPortal()
836    test.globs['plone'] = portal
837    test.globs['transmogrifier'].context = test.globs['plone']
838
839    class BinarySource(SampleSource):
840        classProvides(ISectionBlueprint)
841        implements(ISection)
842
843        def __init__(self, *args, **kw):
844            super(BinarySource, self).__init__(*args, **kw)
845            self.sample = (
846                dict(),
847                dict(_path='not/existing/bar'),
848                dict(_path='spam/eggs/notatcontent'),
849                dict(_path='spam/eggs/foo'),
850            )
851
852    provideUtility(BinarySource,
853        name=u'quintagroup.transmogrifier.tests.binarysource')
854
855from DateTime import DateTime
856
857def catalogSourceSetUp(test):
858    sectionsSetUp(test)
859
860    class MockContent(dict):
861        def __init__(self, **kw):
862            self.update(kw)
863            self['id'] = self.getId
864
865        def getPath(self):
866            return self['path']
867
868        @property
869        def getId(self):
870            path = self.getPath()
871            return path.rsplit('/', 1)[-1]
872
873        @property
874        def portal_type(self):
875            return self['portal_type']
876
877        @property
878        def is_folderish(self):
879            return self['portal_type'] == 'Folder' and True or False
880
881    class MockPortal(dict):
882
883        content = ()
884        def __call__(self, **kw):
885            res = []
886            for obj in self.content:
887                matched = True
888                for index, query in kw.items():
889                    if index not in obj:
890                        matched = False
891                        break
892                    if matched and index == 'modified':
893                        if isinstance(query, dict):
894                            value = query['query']
895                            range_ = query['range']
896                            if range_ == 'min' and DateTime(obj[index]) >= DateTime(value):
897                                matched = True
898                            elif range_ == 'max' and DateTime(obj[index]) <= DateTime(value):
899                                matched = True
900                            else:
901                                matched = False
902                        else:
903                            if DateTime(obj[index]) == DateTime(query):
904                                matched = True
905                            else:
906                                matched = False
907                    elif matched and index == 'path':
908                        if obj[index].startswith(query):
909                            matched = True
910                        else:
911                            matched = False
912                    elif matched:
913                        if obj[index] == query:
914                            matched = True
915                        else:
916                            matched = False
917                if matched:
918                    res.append(obj)
919
920            return res
921
922    portal = MockPortal()
923    doc1 = MockContent(path='/plone/document1', portal_type='Document',
924        modified='2008-11-01T12:00:00Z')
925    folder1 = MockContent(path='/plone/folder1', portal_type='Folder',
926        modified='2008-11-01T12:00:00Z')
927    doc2 = MockContent(path='/plone/folder1/document2', portal_type='Document',
928        modified='2008-11-02T12:00:00Z')
929    doc3 = MockContent(path='/plone/folder1/document3', portal_type='Document',
930        modified='2008-11-02T12:00:00Z')
931    folder2 = MockContent(path='/plone/folder2', portal_type='Folder',
932        modified='2008-11-02T12:00:00Z')
933    doc4 = MockContent(path='/plone/folder2/document4', portal_type='Document',
934        modified='2008-11-01T12:00:00Z')
935    comment = MockContent(path='/plone/folder2/document4/talkback/1234567890', portal_type='Discussion Item',
936        modified='2008-11-02T12:00:00Z')
937    # items are sorted on their modification date
938    portal.content = (doc1, folder1, folder2, doc2, doc3, doc4, comment)
939
940    test.globs['plone'] = portal
941    test.globs['transmogrifier'].context = test.globs['plone']
942
943def test_suite():
944    import sys
945    suite = unittest.findTestCases(sys.modules[__name__])
946    suite.addTests((
947        doctest.DocFileSuite(
948            'sitewalker.txt',
949            setUp=siteWalkerSetUp, tearDown=tearDown),
950        doctest.DocFileSuite(
951            'manifest.txt',
952            setUp=manifestSetUp, tearDown=tearDown),
953        doctest.DocFileSuite(
954            'marshall.txt',
955            setUp=marshallSetUp, tearDown=tearDown),
956        doctest.DocFileSuite(
957            'propertymanager.txt',
958            setUp=propertyManagerSetUp, tearDown=tearDown),
959        doctest.DocFileSuite(
960            'comments.txt',
961            setUp=commentsSetUp, tearDown=tearDown),
962        doctest.DocFileSuite(
963            'datacorrector.txt',
964            setUp=dataCorrectorSetUp, tearDown=tearDown),
965        doctest.DocFileSuite(
966            'writer.txt',
967            setUp=writerSetUp, tearDown=tearDown),
968        doctest.DocFileSuite(
969            'reader.txt',
970            setUp=readerSetUp, tearDown=tearDown),
971        doctest.DocFileSuite(
972            'substitution.txt',
973            setUp=substitutionSetUp, tearDown=tearDown),
974        doctest.DocFileSuite(
975            'xslt.txt',
976            setUp=xsltSetUp, tearDown=tearDown),
977        doctest.DocFileSuite(
978            'binary.txt',
979            setUp=binarySetUp, tearDown=tearDown),
980        doctest.DocFileSuite(
981            'catalogsource.txt',
982            setUp=catalogSourceSetUp, tearDown=tearDown),
983    ))
984    return suite
Note: See TracBrowser for help on using the repository browser.