~azzar1/unity/add-show-desktop-key

1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
1
from nose.tools import assert_equal, raises
2
1294.3.2 by William Grant
Router->Publisher
3
from ivle.webapp.publisher import (INF, InsufficientPathSegments, NoPath,
4
                                   NotFound, RouteConflict, Publisher, ROOT)
1294.2.1 by William Grant
Add an object-traversal-based router.
5
6
class Root(object):
7
    def __init__(self):
8
        self.subjects = {}
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
9
        self.users = {}
1294.2.1 by William Grant
Add an object-traversal-based router.
10
11
    def add_subject(self, subject):
12
        self.subjects[subject.name] = subject
13
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
14
    def add_user(self, user):
15
        self.users[user.login] = user
16
17
class User(object):
18
    def __init__(self, login):
19
        self.login = login
20
1294.2.1 by William Grant
Add an object-traversal-based router.
21
class Subject(object):
22
    def __init__(self, name, code):
23
        self.name = name
24
        self.code = code
25
        self.offerings = {}
26
27
    def add_offering(self, offering):
28
        assert self.name == offering.subject.name
29
        self.offerings[(offering.year, offering.semester)] = offering
30
31
class Offering(object):
32
    def __init__(self, subject, year, semester):
33
        self.subject = subject
34
        self.year = year
35
        self.semester = semester
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
36
        self.projects = {}
37
38
    def add_project(self, project):
39
        assert project.offering is self
40
        self.projects[project.name] = project
1294.2.1 by William Grant
Add an object-traversal-based router.
41
1294.2.36 by William Grant
Replace the tests' OfferingProjects with OfferingFiles.
42
class OfferingFiles(object):
1294.2.22 by William Grant
Test named routes.
43
    def __init__(self, offering):
44
        self.offering = offering
45
1294.2.37 by William Grant
Test a route with infinitely many arguments.
46
class OfferingFile(object):
47
    def __init__(self, offeringfiles, path):
48
        self.offering = offeringfiles.offering
49
        self.path = path
50
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
51
class Project(object):
52
    def __init__(self, offering, name):
53
        self.offering = offering
54
        self.name = name
55
1294.2.37 by William Grant
Test a route with infinitely many arguments.
56
1294.2.1 by William Grant
Add an object-traversal-based router.
57
class View(object):
58
    def __init__(self, context):
59
        self.context = context
60
61
class RootIndex(View):
62
    pass
63
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
64
class UserServeView(View):
65
    pass
66
1294.2.1 by William Grant
Add an object-traversal-based router.
67
class SubjectIndex(View):
68
    pass
69
70
class SubjectEdit(View):
71
    pass
72
73
class OfferingIndex(View):
74
    pass
75
76
class OfferingEdit(View):
77
    pass
78
1294.2.2 by William Grant
Split out views from normal routes, and add a viewset concept.
79
class OfferingAPIIndex(View):
80
    pass
81
1294.2.36 by William Grant
Replace the tests' OfferingProjects with OfferingFiles.
82
class OfferingFilesIndex(View):
1294.2.35 by William Grant
Fix and expand tests to cover new NotFound cases.
83
    pass
84
1294.2.37 by William Grant
Test a route with infinitely many arguments.
85
class OfferingFileIndex(View):
86
    pass
87
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
88
class ProjectIndex(View):
89
    pass
90
1294.2.46 by William Grant
Add tests for default deep views.
91
class OfferingProjects(View):
92
    pass
93
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
94
class OfferingAddProject(View):
95
    pass
96
1693 by William Grant
Add support for "really deep" (more than two segment) views.
97
class OfferingWorksheets(View):
98
    pass
99
100
class OfferingWorksheetMarks(View):
101
    pass
102
103
class OfferingWorksheetCSVMarks(View):
104
    pass
105
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
106
def root_to_subject_or_user(root, name):
107
    if name.startswith('~'):
108
        return root.users.get(name[1:])
1294.2.35 by William Grant
Fix and expand tests to cover new NotFound cases.
109
    return root.subjects.get(name)
1294.2.1 by William Grant
Add an object-traversal-based router.
110
111
def subject_to_offering(subject, year, semester):
1294.2.35 by William Grant
Fix and expand tests to cover new NotFound cases.
112
    return subject.offerings.get((int(year), int(semester)))
1294.2.1 by William Grant
Add an object-traversal-based router.
113
1294.2.36 by William Grant
Replace the tests' OfferingProjects with OfferingFiles.
114
def offering_to_files(offering):
115
    return OfferingFiles(offering)
1294.2.1 by William Grant
Add an object-traversal-based router.
116
1294.2.37 by William Grant
Test a route with infinitely many arguments.
117
def offering_files_to_file(offeringfiles, *path):
118
    return OfferingFile(offeringfiles, path)
119
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
120
def offering_to_project(offering, name):
121
    return offering.projects.get(name)
122
1294.2.1 by William Grant
Add an object-traversal-based router.
123
def subject_url(subject):
124
    return (ROOT, subject.name)
125
126
def offering_url(offering):
127
    return (offering.subject, (str(offering.year), str(offering.semester)))
128
1294.2.40 by William Grant
Test generation of URLs for named routes.
129
def offering_files_url(offeringfiles):
130
    return (offeringfiles.offering, '+files')
1294.2.22 by William Grant
Test named routes.
131
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
132
def project_url(project):
133
    return (project.offering, ('+projects', project.name))
1294.2.1 by William Grant
Add an object-traversal-based router.
134
135
class BaseTest(object):
136
    def setUp(self):
137
        r = Root()
138
        self.r = r
139
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
140
        # A user would be nice.
141
        r.add_user(User('jsmith'))
142
1294.2.1 by William Grant
Add an object-traversal-based router.
143
        # Give us some subjects...
144
        r.add_subject(Subject('info1', '600151'))
145
        r.add_subject(Subject('info2', '600152'))
146
        r.add_subject(Subject('info3', '600251'))
147
148
        # ... and some offerings.
149
        r.subjects['info1'].add_offering(Offering(self.r.subjects['info1'],
150
                                         2008, 1))
151
        r.subjects['info1'].add_offering(Offering(self.r.subjects['info1'],
152
                                         2008, 2))
153
        r.subjects['info1'].add_offering(Offering(self.r.subjects['info1'],
154
                                         2009, 1))
155
        r.subjects['info2'].add_offering(Offering(self.r.subjects['info2'],
156
                                         2008, 2))
157
        r.subjects['info2'].add_offering(Offering(self.r.subjects['info2'],
158
                                         2009, 1))
159
        r.subjects['info3'].add_offering(Offering(self.r.subjects['info3'],
160
                                         2009, 1))
161
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
162
        # A normal project...
163
        r.subjects['info1'].offerings[(2009, 1)].add_project(
164
            Project(r.subjects['info1'].offerings[(2009, 1)], 'p1')
165
            )
166
167
        # And one conflicting with a deep view, just to be nasty.
168
        r.subjects['info1'].offerings[(2009, 1)].add_project(
169
            Project(r.subjects['info1'].offerings[(2009, 1)], '+new')
170
            )
171
1294.2.1 by William Grant
Add an object-traversal-based router.
172
class TestResolution(BaseTest):
1294.2.10 by William Grant
Refactor resolution tests too.
173
    def setUp(self):
174
        super(TestResolution, self).setUp()
1294.3.2 by William Grant
Router->Publisher
175
        self.rtr = Publisher(root=self.r, viewset='browser')
1294.2.10 by William Grant
Refactor resolution tests too.
176
        self.rtr.add_set_switch('api', 'api')
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
177
        self.rtr.add_forward(Root, None, root_to_subject_or_user, 1)
1294.2.10 by William Grant
Refactor resolution tests too.
178
        self.rtr.add_forward(Subject, None, subject_to_offering, 2)
1294.2.36 by William Grant
Replace the tests' OfferingProjects with OfferingFiles.
179
        self.rtr.add_forward(Offering, '+files', offering_to_files, 0)
1294.2.37 by William Grant
Test a route with infinitely many arguments.
180
        self.rtr.add_forward(OfferingFiles, None, offering_files_to_file, INF)
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
181
        self.rtr.add_forward(Offering, '+projects', offering_to_project, 1)
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
182
        self.rtr.add_view(User, None, UserServeView, viewset='browser')
1294.2.10 by William Grant
Refactor resolution tests too.
183
        self.rtr.add_view(Subject, '+index', SubjectIndex, viewset='browser')
184
        self.rtr.add_view(Subject, '+edit', SubjectEdit, viewset='browser')
185
        self.rtr.add_view(Offering, '+index', OfferingIndex, viewset='browser')
186
        self.rtr.add_view(Offering, '+index', OfferingAPIIndex, viewset='api')
1294.2.36 by William Grant
Replace the tests' OfferingProjects with OfferingFiles.
187
        self.rtr.add_view(OfferingFiles, '+index', OfferingFilesIndex,
1294.2.35 by William Grant
Fix and expand tests to cover new NotFound cases.
188
                          viewset='browser')
1294.2.37 by William Grant
Test a route with infinitely many arguments.
189
        self.rtr.add_view(OfferingFile, '+index', OfferingFileIndex,
190
                          viewset='browser')
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
191
        self.rtr.add_view(Project, '+index', ProjectIndex, viewset='browser')
192
        self.rtr.add_view(Offering, ('+projects', '+new'), OfferingAddProject,
193
                          viewset='browser')
1294.2.46 by William Grant
Add tests for default deep views.
194
        self.rtr.add_view(Offering, ('+projects', '+index'), OfferingProjects,
195
                          viewset='browser')
1693 by William Grant
Add support for "really deep" (more than two segment) views.
196
        self.rtr.add_view(Offering, ('+worksheets', '+index'),
197
                          OfferingWorksheets, viewset='browser')
198
        self.rtr.add_view(Offering, ('+worksheets', '+marks', '+index'),
199
                          OfferingWorksheetMarks, viewset='browser')
200
        self.rtr.add_view(Offering, ('+worksheets', '+marks', 'marks.csv'),
201
                          OfferingWorksheetCSVMarks, viewset='browser')
1294.2.10 by William Grant
Refactor resolution tests too.
202
1294.2.23 by William Grant
Stop testing resolutions with views.
203
    def testOneRoute(self):
204
        assert_equal(self.rtr.resolve('/info1'),
205
                     (self.r.subjects['info1'], SubjectIndex, ())
206
                     )
207
        assert_equal(self.rtr.resolve('/info3'),
208
                     (self.r.subjects['info3'], SubjectIndex, ())
209
                     )
210
211
    def testTwoRoutes(self):
212
        assert_equal(self.rtr.resolve('/info1/2009/1'),
213
             (self.r.subjects['info1'].offerings[(2009, 1)], OfferingIndex, ())
214
             )
215
        assert_equal(self.rtr.resolve('/info2/2008/2'),
216
             (self.r.subjects['info2'].offerings[(2008, 2)], OfferingIndex, ())
217
             )
1294.2.10 by William Grant
Refactor resolution tests too.
218
1294.2.22 by William Grant
Test named routes.
219
    def testNamedRoute(self):
1294.2.36 by William Grant
Replace the tests' OfferingProjects with OfferingFiles.
220
        assert_equal(type(self.rtr.resolve('/info1/2009/1/+files')[0]),
221
                     OfferingFiles
1294.2.22 by William Grant
Test named routes.
222
                    )
1294.2.36 by William Grant
Replace the tests' OfferingProjects with OfferingFiles.
223
        assert_equal(self.rtr.resolve('/info1/2009/1/+files')[0].offering,
1294.2.22 by William Grant
Test named routes.
224
                     self.r.subjects['info1'].offerings[(2009, 1)]
225
                    )
226
1294.2.23 by William Grant
Stop testing resolutions with views.
227
    def testNonDefaultView(self):
1294.2.10 by William Grant
Refactor resolution tests too.
228
        assert_equal(self.rtr.resolve('/info1/+edit'),
1294.2.11 by William Grant
Revise generation and resolution tests to involve subpaths.
229
                     (self.r.subjects['info1'], SubjectEdit, ())
1294.2.10 by William Grant
Refactor resolution tests too.
230
                     )
1294.2.1 by William Grant
Add an object-traversal-based router.
231
1294.2.3 by William Grant
Add tests to complete coverage.
232
    def testDefaultView(self):
1294.2.10 by William Grant
Refactor resolution tests too.
233
        assert_equal(self.rtr.resolve('/info1'),
1294.2.11 by William Grant
Revise generation and resolution tests to involve subpaths.
234
                     (self.r.subjects['info1'], SubjectIndex, ())
235
                     )
236
237
    def testViewWithSubpath(self):
238
        assert_equal(self.rtr.resolve('/info1/+edit/foo/bar'),
1294.2.13 by William Grant
Fix view mistake in test.
239
                     (self.r.subjects['info1'], SubjectEdit, ('foo', 'bar'))
1294.2.10 by William Grant
Refactor resolution tests too.
240
                     )
241
1294.2.35 by William Grant
Fix and expand tests to cover new NotFound cases.
242
    def testNoDefaultView(self):
243
        try:
244
            self.rtr.default = 'not+index'
245
            self.rtr.resolve('/info1')
246
        except NotFound, e:
247
            assert_equal(e.args, (self.r.subjects['info1'], '+index', ()))
248
        except:
249
            raise
250
        else:
251
            raise AssertionError('did not raise NotFound')
252
        finally:
253
            self.rtr.default = '+index'
254
255
    def testMissingView(self):
256
        try:
257
            self.rtr.resolve('/info1/+foo')
258
        except NotFound, e:
259
            assert_equal(e.args, (self.r.subjects['info1'], '+foo', ()))
260
        except:
261
            raise
262
        else:
263
            raise AssertionError('did not raise NotFound')
264
1294.2.10 by William Grant
Refactor resolution tests too.
265
    def testViewSetSeparation(self):
1294.2.35 by William Grant
Fix and expand tests to cover new NotFound cases.
266
        try:
267
            self.rtr.resolve('/api/info1/+edit')
268
        except NotFound, e:
269
            assert_equal(e.args, (self.r.subjects['info1'], '+edit', ()))
270
        except:
271
            raise
272
        else:
273
            raise AssertionError('did not raise NotFound')
274
275
    def testRouteReturningNone(self):
276
        try:
277
            self.rtr.resolve('/info9/+index')
278
        except NotFound, e:
279
            assert_equal(e.args, (self.r, 'info9', ('+index',)))
280
        except:
281
            raise
282
        else:
283
            raise AssertionError('did not raise NotFound')
1294.2.10 by William Grant
Refactor resolution tests too.
284
1294.2.37 by William Grant
Test a route with infinitely many arguments.
285
    def testRouteWithInfinitelyManyArguments(self):
286
        o, v, sp = self.rtr.resolve('/info1/2009/1/+files/foo/bar/baz')
287
288
        assert_equal(type(o), OfferingFile)
289
        assert_equal(o.path, ('foo', 'bar', 'baz'))
290
        assert_equal(o.offering, self.r.subjects['info1'].offerings[(2009, 1)])
291
        assert_equal(v, OfferingFileIndex)
292
        assert_equal(sp, ())
293
1294.2.38 by William Grant
Test behaviour when a nonexistent route is specified.
294
    def testMissingRoute(self):
295
        try:
296
            self.rtr.resolve('/info1/2009/1/+foo')
297
        except NotFound, e:
298
            assert_equal(e.args, (
299
                self.r.subjects['info1'].offerings[(2009, 1)],
300
                '+foo',
301
                ()
302
                ))
303
        except:
304
            raise
305
        else:
306
            raise AssertionError('did not raise NotFound')
307
1294.2.10 by William Grant
Refactor resolution tests too.
308
    def testAlternateViewSetWithDefault(self):
309
        assert_equal(self.rtr.resolve('/info1/2009/1'),
1294.2.11 by William Grant
Revise generation and resolution tests to involve subpaths.
310
             (self.r.subjects['info1'].offerings[(2009, 1)], OfferingIndex, ())
311
             )
1294.2.2 by William Grant
Split out views from normal routes, and add a viewset concept.
312
1294.2.10 by William Grant
Refactor resolution tests too.
313
        assert_equal(self.rtr.resolve('/api/info1/2009/1'),
1294.2.11 by William Grant
Revise generation and resolution tests to involve subpaths.
314
          (self.r.subjects['info1'].offerings[(2009, 1)], OfferingAPIIndex, ())
315
          )
1294.2.3 by William Grant
Add tests to complete coverage.
316
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
317
    def testDeepView(self):
318
        assert_equal(self.rtr.resolve('/info1/2009/1/+projects/+new'),
319
             (self.r.subjects['info1'].offerings[(2009, 1)],
320
              OfferingAddProject, ())
321
             )
322
1294.2.46 by William Grant
Add tests for default deep views.
323
    def testDefaultDeepView(self):
324
        assert_equal(self.rtr.resolve('/info1/2009/1/+projects'),
325
             (self.r.subjects['info1'].offerings[(2009, 1)],
326
              OfferingProjects, ())
327
             )
328
1693 by William Grant
Add support for "really deep" (more than two segment) views.
329
    def testAnotherDefaultDeepView(self):
330
        assert_equal(self.rtr.resolve('/info1/2009/1/+worksheets'),
331
             (self.r.subjects['info1'].offerings[(2009, 1)],
332
              OfferingWorksheets, ())
333
             )
334
335
    def testReallyDeepView(self):
336
        assert_equal(
337
             self.rtr.resolve('/info1/2009/1/+worksheets/+marks/marks.csv'),
338
             (self.r.subjects['info1'].offerings[(2009, 1)],
339
              OfferingWorksheetCSVMarks, ())
340
             )
341
342
    def testDefaultReallyDeepView(self):
343
        assert_equal(self.rtr.resolve('/info1/2009/1/+worksheets/+marks'),
344
             (self.r.subjects['info1'].offerings[(2009, 1)],
345
              OfferingWorksheetMarks, ())
346
             )
347
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
348
    def testNamedRouteWithDeepView(self):
349
        assert_equal(self.rtr.resolve('/info1/2009/1/+projects/p1'),
350
             (self.r.subjects['info1'].offerings[(2009, 1)].projects['p1'],
351
              ProjectIndex, ())
352
             )
353
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
354
    def testNullPathView(self):
355
        """Verify that views can be placed immediately under an object.
356
357
        There are some cases in which it is useful for a view with a
358
        subpath to exist immediately under an object, with no name.
359
        """
360
        assert_equal(self.rtr.resolve('/~jsmith/foo/bar'),
361
             (self.r.users['jsmith'], UserServeView, ('foo', 'bar')))
362
1795 by William Grant
Trailing slashes in URLs can now be detected by views accepting subpaths.
363
    def testTrailingSlashResolvesToDefaultView(self):
364
        assert_equal(
365
             self.rtr.resolve('/info1/2009/1/'),
366
             (self.r.subjects['info1'].offerings[(2009, 1)],
367
              OfferingIndex, ())
368
             )
369
370
    def testTrailingSlashResolvesToDeepDefaultView(self):
371
        assert_equal(
372
             self.rtr.resolve('/info1/2009/1/+worksheets/+marks/'),
373
             (self.r.subjects['info1'].offerings[(2009, 1)],
374
              OfferingWorksheetMarks, ())
375
             )
376
377
    def testSubpathIndicatesTrailingSlash(self):
378
        assert_equal(
379
             self.rtr.resolve('/info1/2009/1/+index/'),
380
             (self.r.subjects['info1'].offerings[(2009, 1)],
381
              OfferingIndex, ('',))
382
             )
1294.2.41 by William Grant
Test deep views (views with names consisting of multiple segments).
383
1294.2.1 by William Grant
Add an object-traversal-based router.
384
class TestGeneration(BaseTest):
1294.2.9 by William Grant
Refactor generation tests.
385
    def setUp(self):
386
        super(TestGeneration, self).setUp()
1294.3.2 by William Grant
Router->Publisher
387
        self.rtr = Publisher(root=self.r, viewset='browser')
1294.2.9 by William Grant
Refactor generation tests.
388
        self.rtr.add_set_switch('api', 'api')
389
        self.rtr.add_reverse(Subject, subject_url)
390
        self.rtr.add_reverse(Offering, offering_url)
1294.2.40 by William Grant
Test generation of URLs for named routes.
391
        self.rtr.add_reverse(OfferingFiles, offering_files_url)
1294.2.43 by William Grant
Test deep view generation.
392
        self.rtr.add_reverse(Project, project_url)
1294.2.9 by William Grant
Refactor generation tests.
393
        self.rtr.add_view(Subject, '+index', SubjectIndex, viewset='browser')
394
        self.rtr.add_view(Subject, '+edit', SubjectEdit, viewset='browser')
395
        self.rtr.add_view(Offering, '+index', OfferingIndex, viewset='browser')
396
        self.rtr.add_view(Offering, '+index', OfferingAPIIndex, viewset='api')
1294.2.43 by William Grant
Test deep view generation.
397
        self.rtr.add_view(Project, '+index', ProjectIndex, viewset='browser')
398
        self.rtr.add_view(Offering, ('+projects', '+new'), OfferingAddProject,
399
                          viewset='browser')
1294.2.46 by William Grant
Add tests for default deep views.
400
        self.rtr.add_view(Offering, ('+projects', '+index'), OfferingProjects,
401
                          viewset='browser')
1294.2.9 by William Grant
Refactor generation tests.
402
1294.2.1 by William Grant
Add an object-traversal-based router.
403
    def testOneLevel(self):
1294.2.9 by William Grant
Refactor generation tests.
404
        assert_equal(self.rtr.generate(self.r.subjects['info1']), '/info1')
1294.2.1 by William Grant
Add an object-traversal-based router.
405
406
    def testTwoLevel(self):
1294.2.9 by William Grant
Refactor generation tests.
407
        assert_equal(
408
            self.rtr.generate(self.r.subjects['info1'].offerings[(2009, 1)]),
409
            '/info1/2009/1'
410
            )
411
        assert_equal(
412
            self.rtr.generate(self.r.subjects['info2'].offerings[(2008, 2)]),
413
            '/info2/2008/2'
414
            )
1294.2.1 by William Grant
Add an object-traversal-based router.
415
1294.2.40 by William Grant
Test generation of URLs for named routes.
416
    def testNamedRoute(self):
417
        assert_equal(self.rtr.generate(
418
                OfferingFiles(self.r.subjects['info1'].offerings[(2009, 1)])),
419
                '/info1/2009/1/+files'
420
            )
421
1294.2.9 by William Grant
Refactor generation tests.
422
    def testView(self):
423
        assert_equal(self.rtr.generate(self.r.subjects['info1'], SubjectEdit),
424
                     '/info1/+edit'
425
                     )
1294.2.1 by William Grant
Add an object-traversal-based router.
426
1294.2.4 by William Grant
Support generation of view URLs.
427
    def testDefaultView(self):
1294.2.9 by William Grant
Refactor generation tests.
428
        assert_equal(
429
            self.rtr.generate(self.r.subjects['info1'].offerings[(2009, 1)],
430
                              OfferingIndex
431
                              ),
432
            '/info1/2009/1'
433
            )
1294.2.1 by William Grant
Add an object-traversal-based router.
434
1294.2.11 by William Grant
Revise generation and resolution tests to involve subpaths.
435
    def testViewWithSubpath(self):
436
        assert_equal(self.rtr.generate(self.r.subjects['info1'], SubjectEdit,
437
                                       ('foo', 'bar')),
438
                     '/info1/+edit/foo/bar'
439
                     )
440
441
    def testViewWithStringSubpath(self):
442
        assert_equal(self.rtr.generate(self.r.subjects['info1'], SubjectEdit,
443
                                       'foo/bar'),
444
                     '/info1/+edit/foo/bar'
445
                     )
446
1294.2.9 by William Grant
Refactor generation tests.
447
    def testAlternateViewSetWithDefault(self):
448
        assert_equal(
449
            self.rtr.generate(self.r.subjects['info1'].offerings[(2009, 1)],
450
                              OfferingAPIIndex
451
                              ),
452
            '/api/info1/2009/1'
453
            )
1294.2.4 by William Grant
Support generation of view URLs.
454
1294.2.43 by William Grant
Test deep view generation.
455
    def testDeepView(self):
456
        assert_equal(
457
            self.rtr.generate(
458
                self.r.subjects['info1'].offerings[(2009, 1)],
459
                OfferingAddProject
460
                ),
461
        '/info1/2009/1/+projects/+new'
462
        )
463
1294.2.46 by William Grant
Add tests for default deep views.
464
    def testDefaultDeepView(self):
465
        assert_equal(
466
            self.rtr.generate(
467
                self.r.subjects['info1'].offerings[(2009, 1)],
468
                OfferingProjects
469
                ),
470
        '/info1/2009/1/+projects'
471
        )
472
473
    def testDefaultDeepViewWithSubpath(self):
474
        assert_equal(
475
            self.rtr.generate(
476
                self.r.subjects['info1'].offerings[(2009, 1)],
477
                OfferingProjects, ('foo', 'bar')
478
                ),
479
        '/info1/2009/1/+projects/+index/foo/bar'
480
        )
481
1294.2.43 by William Grant
Test deep view generation.
482
    def testNamedRouteWithDeepView(self):
483
        assert_equal(
484
            self.rtr.generate(
485
                self.r.subjects['info1'].offerings[(2009, 1)].projects['p1'],
486
                ProjectIndex
487
                ),
488
        '/info1/2009/1/+projects/p1'
489
        )
490
1294.3.1 by William Grant
Allow reverse routes to return the real root too.
491
    def testRoot(self):
492
        assert_equal(self.rtr.generate(self.r), '/')
1294.2.43 by William Grant
Test deep view generation.
493
1294.2.1 by William Grant
Add an object-traversal-based router.
494
495
class TestErrors(BaseTest):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
496
    def setUp(self):
497
        super(TestErrors, self).setUp()
1294.3.2 by William Grant
Router->Publisher
498
        self.rtr = Publisher(root=self.r)
1294.2.136 by William Grant
Add publisher support for nameless views, directly under an object.
499
        self.rtr.add_forward(Root, None, root_to_subject_or_user, 1)
1294.2.6 by William Grant
Refactor the error tests, using a single router.
500
        self.rtr.add_forward(Subject, '+foo', lambda s: s.name + 'foo', 0)
501
        self.rtr.add_forward(Subject, None, subject_to_offering, 2)
502
        self.rtr.add_reverse(Subject, subject_url)
503
        self.rtr.add_reverse(Offering, offering_url)
504
        self.rtr.add_view(Offering, '+index', OfferingIndex)
505
        self.rtr.add_view(Offering, '+index', OfferingAPIIndex, viewset='api')
506
        self.rtr.add_set_switch('rest', 'rest')
507
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
508
    @raises(RouteConflict)
1294.2.1 by William Grant
Add an object-traversal-based router.
509
    def testForwardConflict(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
510
        self.rtr.add_forward(Subject, '+foo', object(), 2)
1294.2.1 by William Grant
Add an object-traversal-based router.
511
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
512
    @raises(RouteConflict)
1294.2.1 by William Grant
Add an object-traversal-based router.
513
    def testReverseConflict(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
514
        self.rtr.add_reverse(Subject, object())
1294.2.1 by William Grant
Add an object-traversal-based router.
515
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
516
    @raises(RouteConflict)
1294.2.3 by William Grant
Add tests to complete coverage.
517
    def testViewConflict(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
518
        self.rtr.add_view(Offering, '+index', object())
519
520
    @raises(RouteConflict)
521
    def testSetSwitchForwardConflict(self):
522
        self.rtr.add_set_switch('rest', 'foo')
523
524
    @raises(RouteConflict)
525
    def testSetSwitchReverseConflict(self):
526
        self.rtr.add_set_switch('bar', 'rest')
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
527
528
    @raises(NoPath)
1294.2.1 by William Grant
Add an object-traversal-based router.
529
    def testNoPath(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
530
        self.rtr.generate(object())
1294.2.1 by William Grant
Add an object-traversal-based router.
531
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
532
    @raises(NoPath)
1294.2.4 by William Grant
Support generation of view URLs.
533
    def testNoSetSwitch(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
534
        self.rtr.generate(self.r.subjects['info1'].offerings[(2009, 1)],
535
                          OfferingAPIIndex)
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
536
537
    @raises(NoPath)
1294.2.4 by William Grant
Support generation of view URLs.
538
    def testUnregisteredView(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
539
        self.rtr.generate(self.r.subjects['info1'], SubjectIndex)
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
540
541
    @raises(NotFound)
1294.2.1 by William Grant
Add an object-traversal-based router.
542
    def testNotFound(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
543
        self.rtr.resolve('/bar')
1294.2.1 by William Grant
Add an object-traversal-based router.
544
1294.2.5 by William Grant
Use nose.tools.raises in the error tests.
545
    @raises(InsufficientPathSegments)
1294.2.1 by William Grant
Add an object-traversal-based router.
546
    def testInsufficientPathSegments(self):
1294.2.6 by William Grant
Refactor the error tests, using a single router.
547
        self.rtr.resolve('/info1/foo')