23
23
from epsilon import extime
24
24
from epsilon.extime import Time
25
25
from epsilon.structlike import record
26
from epsilon.hotfix import require
28
require('twisted', 'trial_assertwarns')
27
30
from axiom.store import Store, AtomicFile
28
from axiom.dependency import installOn, installedOn
31
from axiom.dependency import installOn
29
32
from axiom.item import Item
30
from axiom.attributes import inmemory, text
33
from axiom.attributes import inmemory, text, AND
31
34
from axiom.errors import DeletionDisallowed
35
from axiom import tags
33
37
from axiom.userbase import LoginSystem
48
52
_stringifyKeys, makeThumbnail, _descriptiveIdentifier,
49
53
ReadOnlyContactInfoView, PersonSummaryView, MugshotUploadForm,
50
54
ORGANIZER_VIEW_STATES, MugshotResource, Notes, NotesContactType,
51
ReadOnlyNotesView, ContactGroup)
55
ReadOnlyNotesView, ContactGroup, AllPeopleFilter, VIPPeopleFilter,
53
58
from xmantissa.webapp import PrivateApplication
54
59
from xmantissa.liveform import (
56
61
ListChanges, CreateObject, EditObject, FormParameter, ChoiceParameter,
58
63
from xmantissa.ixmantissa import (
59
IOrganizerPlugin, IContactType, IWebTranslator, IPersonFragment)
64
IOrganizerPlugin, IContactType, IWebTranslator, IPersonFragment,
60
66
from xmantissa.signup import UserInfo
67
from xmantissa.test.peopleutil import PeopleFilterTestMixin
63
70
# the number of non-plugin IContactType implementations provided by Mantissa.
64
71
builtinContactTypeCount = 5
72
# the number of non-plugin IPeopleFilter implementations provided by Mantissa
73
builtinPeopleFilterCount = 2
77
class AllPeopleFilterTests(PeopleFilterTestMixin, unittest.TestCase):
79
Tests for L{AllPeopleFilter}.
81
peopleFilterClass = AllPeopleFilter
82
peopleFilterName = 'All'
85
def test_queryComparison(self):
87
L{AllPeopleFilter}'s query comparison should include all people.
90
self.peopleFilterClass().getPeopleQueryComparison(Store()),
95
class VIPPeopleFilterTests(PeopleFilterTestMixin, unittest.TestCase):
97
Tests for L{VIPPeopleFilter}.
99
peopleFilterClass = VIPPeopleFilter
100
peopleFilterName = 'VIP'
103
def test_queryComparison(self):
105
L{VIPPeopleFilter}'s query comparison should include only VIP people.
107
self.assertComparisonEquals(Person.vip == True)
111
class TaggedPeopleFilterTests(unittest.TestCase):
113
Tests for L{TaggedPeopleFilter}.
115
# this TestCase doesn't inherit from PeopleFilterTestMixin because of the
116
# constructor argument and more complicated query.
118
def test_implementsInterface(self):
120
L{TaggedPeopleFilter} should provide L{IPeopleFilter}.
123
IPeopleFilter.providedBy(TaggedPeopleFilter(u'tag')))
126
def test_filterName(self):
128
Our L{TaggedPeopleFilter}'s I{filterName} should be the tag passed to
132
TaggedPeopleFilter(u'test_filterName').filterName,
136
def test_queryComparison(self):
138
L{TaggedPeopleFilter}'s query comparison should include only people
139
who have had a certain tag applied to them.
141
actualComparison = TaggedPeopleFilter(
142
u'test_queryOrdering').getPeopleQueryComparison(Store())
143
expectedComparison = AND(
144
tags.Tag.object == Person.storeID,
145
tags.Tag.name == u'test_queryOrdering')
146
# none of the Axiom query objects have meaningful equality
147
# comparisons, but their string representations are just as good to
150
str(actualComparison), str(expectedComparison))
1618
def test_getPeopleFilters(self):
1620
L{Organizer.getPeopleFilters} should return an iterable of all of the
1621
L{IPeopleFilter} plugins available in the store.
1623
firstPeopleFilters = [object(), object()]
1624
firstContactPowerup = StubOrganizerPlugin(
1625
store=self.store, peopleFilters=firstPeopleFilters)
1627
firstContactPowerup, IOrganizerPlugin, priority=1)
1629
secondPeopleFilters = [object()]
1630
secondContactPowerup = StubOrganizerPlugin(
1631
store=self.store, peopleFilters=secondPeopleFilters)
1633
secondContactPowerup, IOrganizerPlugin, priority=0)
1636
list(self.organizer.getPeopleFilters())[
1637
builtinPeopleFilterCount:],
1638
firstPeopleFilters + secondPeopleFilters)
1641
def test_getPeopleFiltersTags(self):
1643
L{Organizer.getPeopleFilters} should include one L{TaggedPeopleFilter}
1644
for each tag which has been applied to a person.
1646
personTags = list(u'xac')
1647
catalog = tags.Catalog(store=self.store)
1648
for personTag in personTags:
1649
catalog.tag(Person(store=self.store), personTag)
1650
peopleFilters = list(self.organizer.getPeopleFilters())[
1651
builtinPeopleFilterCount:]
1652
self.assertEqual(len(peopleFilters), len(personTags))
1653
for (peopleFilter, personTag) in zip(peopleFilters, sorted(personTags)):
1654
self.assertTrue(isinstance(peopleFilter, TaggedPeopleFilter))
1655
self.assertEqual(peopleFilter.filterName, personTag)
1518
1658
def test_createPerson(self):
1520
1660
L{Organizer.createPerson} should instantiate and return a L{Person} item
2138
2278
self.assertEqual(tab.linkURL, None)
2281
def test_getPeopleTags(self):
2283
L{Organizer.getPeopleTags} should return a set containing each tag
2284
which has been applied to a L{Person}.
2286
alice = self.organizer.createPerson(u'Alice')
2287
frank = self.organizer.createPerson(u'Frank')
2288
catalog = tags.Catalog(store=self.store)
2289
catalog.tag(alice, u'person')
2290
catalog.tag(frank, u'person')
2291
catalog.tag(alice, u'girl')
2292
catalog.tag(frank, u'boy')
2293
# tag the organizer for laughs
2294
catalog.tag(self.organizer, u'organizer')
2296
self.organizer.getPeopleTags(),
2297
set(('person', 'girl', 'boy')))
2142
2301
class POBox(Item):
2143
2302
number = text()
2605
2764
+ [storeOwnerPersonName]))
2767
def test_filterByFilter(self):
2769
L{PersonScrollingFragment.filterByFilter} should change the scrolltable's
2770
base constraint to the query comparison of the named filter.
2772
queryComparison = object()
2773
class MockPeopleFilter:
2774
def getPeopleQueryComparison(_self, store):
2775
self.assertIdentical(store, self.store)
2776
return queryComparison
2777
fragment = PersonScrollingFragment(
2781
StubTranslator(None, None))
2782
fragment.filters = {
2783
u'test_filterByFilter': MockPeopleFilter()}
2784
filterByFilter = expose.get(fragment, 'filterByFilter')
2785
filterByFilter(u'test_filterByFilter')
2786
self.assertIdentical(
2787
fragment.baseConstraint, queryComparison)
2609
2791
class StubOrganizer(object):
2634
2816
@ivar groupedReadOnlyViewPeople: A list of the arguments passed to
2635
2817
L{groupReadOnlyViews}.
2819
@ivar peopleTags: The value to return from L{getPeopleTags}.
2820
@type peopleTags: C{list}
2822
@ivar peopleFilters: The sequence to return from L{getPeopleFilters}.
2823
@type peopleFilters: C{list}
2637
2825
_webTranslator = StubTranslator(None, None)
2639
2827
def __init__(self, store=None, peoplePlugins=None, contactTypes=None,
2640
2828
deletedPeople=None, editedPeople=None,
2641
contactEditorialParameters=None, groupedReadOnlyViews=None):
2829
contactEditorialParameters=None, groupedReadOnlyViews=None,
2830
peopleTags=None, peopleFilters=None):
2642
2831
self.store = store
2643
2832
self.people = {}
2644
2833
if peoplePlugins is None:
2737
2946
def test_peopleTable(self):
2739
L{OrganizerFragment.render_peopleTable} should return a
2948
L{OrganizerFragment}'s I{peopleTable} renderer should return a
2740
2949
L{PersonScrollingFragment}.
2742
request = FakeRequest(args={})
2743
scroller = self.fragment.render_peopleTable(request, None)
2951
peopleTableRenderer = renderer.get(self.fragment, 'peopleTable')
2952
scroller = peopleTableRenderer(None, None)
2744
2953
self.assertTrue(isinstance(scroller, PersonScrollingFragment))
2956
def test_peopleFilters(self):
2958
L{OrganizerFragment}'s I{peopleFilters} renderer should return an
2959
instance of its tag's I{filter} pattern for each filter, except the
2960
first, which should use the I{selected-filter} pattern.
2962
filterNames = list('acyx')
2963
peopleFilters = [record('filterName')(name) for name in filterNames]
2964
self.organizer.peopleFilters = peopleFilters
2965
peopleFiltersRenderer = renderer.get(self.fragment, 'peopleFilters')
2967
div(usedpattern='filter', pattern='filter')[slot('name')],
2968
div(usedpattern='selected-filter',
2969
pattern='selected-filter')[slot('name')]]
2970
patterns = list(peopleFiltersRenderer(None, tag))
2971
self.assertEqual(len(patterns), len(peopleFilters))
2973
selectedPattern = patterns.pop(0)
2974
selectedFilterName = filterNames.pop(0)
2976
selectedPattern.slotData, {'name': selectedFilterName})
2978
selectedPattern.attributes['usedpattern'], 'selected-filter')
2980
for (pattern, filterName) in zip(patterns, filterNames):
2981
self.assertEqual(pattern.slotData, {'name': filterName})
2982
self.assertEqual(pattern.attributes['usedpattern'], 'filter')
2747
2985
def test_getAddPerson(self):
2749
2987
L{OrganizerFragment.getAddPerson} should return an