Permalink
Browse files

Merge branch 'release/version1.0'

  • Loading branch information...
2 parents 077b944 + d088772 commit 237e871c9c4f6a4e0b9ed12a7f22946382000c78 @peterbe peterbe committed Dec 22, 2011
Showing with 44,676 additions and 10,199 deletions.
  1. +5 −0 .gitignore
  2. +3 −0 .gitmodules
  3. +6 −38 README.md
  4. +1 −0 apps/autocomplete/__init__.py
  5. +1 −0 apps/autocomplete/models.py
  6. +210 −0 apps/autocomplete/tests.py
  7. +46 −0 apps/autocomplete/urls.py
  8. +86 −0 apps/autocomplete/views.py
  9. +0 −10 apps/commons/context_processors.py
  10. +0 −68 apps/commons/helpers.py
  11. +0 −58 apps/commons/middleware.py
  12. +0 −94 apps/commons/tests/test_accepted_locales.py
  13. +0 −50 apps/commons/tests/test_migrations.py
  14. +0 −115 apps/commons/urlresolvers.py
  15. 0 apps/{commons → dates}/__init__.py
  16. 0 apps/{pto → dates}/context_processors.py
  17. +29 −0 apps/dates/csv_export.py
  18. +1 −5 apps/{pto → dates}/decorators.py
  19. +188 −0 apps/dates/forms.py
  20. +129 −0 apps/dates/helpers.py
  21. +146 −0 apps/dates/models.py
  22. +4 −0 apps/dates/templates/dates/add.html
  23. +1 −0 apps/dates/templates/dates/add_hours.html
  24. +35 −0 apps/dates/templates/dates/emails_sent.html
  25. +54 −0 apps/dates/templates/dates/following.html
  26. +117 −0 apps/dates/templates/dates/home.html
  27. +53 −0 apps/dates/templates/dates/hours.html
  28. +187 −0 apps/dates/templates/dates/list.html
  29. +5 −0 apps/dates/templates/dates/notification.txt
  30. +71 −0 apps/dates/templates/dates/notify.html
  31. 0 apps/{pto → dates}/templates/pto/home.html
  32. +1 −0 apps/dates/tests/__init__.py
  33. +61 −0 apps/dates/tests/test__utils.py
  34. +157 −0 apps/dates/tests/test_models.py
  35. +2,160 −0 apps/dates/tests/test_views.py
  36. +20 −0 apps/dates/urls.py
  37. +25 −0 apps/dates/utils/__init__.py
  38. +13 −0 apps/dates/utils/countrytotals.py
  39. +33 −0 apps/dates/utils/decorators.py
  40. +1 −0 apps/dates/utils/ldap_utils.py
  41. +1,040 −0 apps/dates/views.py
  42. +0 −35 apps/examples/templates/examples/bleach.html
  43. +0 −26 apps/examples/templates/examples/home.html
  44. +0 −7 apps/examples/urls.py
  45. +0 −29 apps/examples/views.py
  46. 0 apps/{commons/tests → legacy}/__init__.py
  47. 0 apps/{examples → legacy/management}/__init__.py
  48. 0 apps/{pto → legacy/management/commands}/__init__.py
  49. +163 −0 apps/legacy/management/commands/migrate_pto.py
  50. +17 −0 apps/legacy/models.py
  51. 0 apps/{commons/models.py → mobile/__init__.py}
  52. +22 −0 apps/mobile/helpers.py
  53. +1 −0 apps/mobile/models.py
  54. +20 −0 apps/mobile/templates/mobile/appcache.html
  55. +16 −0 apps/mobile/templates/mobile/base.html
  56. +1 −0 apps/mobile/templates/mobile/home.html
  57. +1 −0 apps/mobile/templates/mobile/homeicon.html
  58. +40 −0 apps/mobile/templates/mobile/mobile.html
  59. +38 −0 apps/mobile/templates/mobile/page.hours.html
  60. +12 −0 apps/mobile/templates/mobile/page.left.html
  61. +27 −0 apps/mobile/templates/mobile/page.login.html
  62. +17 −0 apps/mobile/templates/mobile/page.logout.html
  63. +32 −0 apps/mobile/templates/mobile/page.notify.html
  64. +16 −0 apps/mobile/templates/mobile/page.rightnow.html
  65. +31 −0 apps/mobile/templates/mobile/page.settings.html
  66. +11 −0 apps/mobile/templates/mobile/page.taken.html
  67. +486 −0 apps/mobile/tests.py
  68. +52 −0 apps/mobile/urls.py
  69. +288 −0 apps/mobile/views.py
  70. +0 −57 apps/pto/helpers.py
  71. +0 −4 apps/pto/tests.py
  72. +0 −13 apps/pto/urls.py
  73. +0 −53 apps/pto/views.py
  74. +1 −0 apps/users/__init__.py
  75. +30 −0 apps/users/admin.py
  76. 0 apps/{examples/models.py → users/auth/__init__.py}
  77. +171 −0 apps/users/auth/backends.py
  78. +61 −0 apps/users/email_auth_backend.py
  79. +108 −0 apps/users/forms.py
  80. +59 −0 apps/users/models.py
  81. +30 −0 apps/users/templates/users/login.html
  82. +64 −0 apps/users/templates/users/profile.html
  83. +543 −0 apps/users/tests.py
  84. +45 −0 apps/users/urls.py
  85. 0 apps/{pto/models.py → users/utils/__init__.py}
  86. +106 −0 apps/users/utils/ldap_lookup.py
  87. +52 −0 apps/users/utils/ldap_mock.py
  88. +153 −0 apps/users/views.py
  89. +1 −0 lib/__init__.py
  90. +6 −0 lib/country_aliases.py
  91. +13 −50 manage.py
  92. +15 −0 media/css/dates/following.css
  93. +71 −0 media/css/dates/home.css
  94. +43 −0 media/css/dates/hours.css
  95. +9 −0 media/css/dates/notify.css
  96. +519 −0 media/css/demo_table_jui.css
  97. BIN media/css/images/asc.gif
  98. BIN media/css/images/background.jpg
  99. BIN media/css/images/bg.png
  100. BIN media/css/images/desc.gif
  101. BIN media/css/images/pto.png
  102. BIN media/css/images/sort.gif
  103. BIN media/css/images/throbber.png
  104. +538 −0 media/css/libs/datatable/css/demo_table.css
  105. BIN media/css/libs/datatable/images/back_disabled.jpg
  106. BIN media/css/libs/datatable/images/back_enabled.jpg
  107. BIN media/css/libs/datatable/images/forward_disabled.jpg
  108. BIN media/css/libs/datatable/images/forward_enabled.jpg
  109. BIN media/css/libs/datatable/images/sort_asc.png
  110. BIN media/css/libs/datatable/images/sort_asc_disabled.png
  111. BIN media/css/libs/datatable/images/sort_both.png
  112. BIN media/css/libs/datatable/images/sort_desc.png
  113. BIN media/css/libs/datatable/images/sort_desc_disabled.png
  114. +60 −0 media/css/libs/fireworks.css
  115. +618 −0 media/css/libs/fullcalendar.css
  116. +61 −0 media/css/libs/fullcalendar.print.css
  117. BIN media/css/libs/images/ajax-loader.png
  118. BIN media/css/libs/images/icons-18-black.png
  119. BIN media/css/libs/images/icons-18-white.png
  120. BIN media/css/libs/images/icons-36-black.png
  121. BIN media/css/libs/images/icons-36-white.png
  122. +1,845 −0 media/css/libs/jquery.mobile-1.0rc3.css
  123. +2 −0 media/css/libs/jquery.mobile-1.0rc3.min.css
  124. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png
  125. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_flat_55_fbec88_40x100.png
  126. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png
  127. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_glass_85_dfeffc_1x400.png
  128. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_glass_95_fef1ec_1x400.png
  129. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
  130. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
  131. BIN media/css/libs/jquery_ui/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
  132. BIN media/css/libs/jquery_ui/redmond/images/ui-icons_217bc0_256x240.png
  133. BIN media/css/libs/jquery_ui/redmond/images/ui-icons_2e83ff_256x240.png
  134. BIN media/css/libs/jquery_ui/redmond/images/ui-icons_469bdd_256x240.png
  135. BIN media/css/libs/jquery_ui/redmond/images/ui-icons_6da8d5_256x240.png
  136. BIN media/css/libs/jquery_ui/redmond/images/ui-icons_cd0a0a_256x240.png
  137. BIN media/css/libs/jquery_ui/redmond/images/ui-icons_d8e7f3_256x240.png
  138. BIN media/css/libs/jquery_ui/redmond/images/ui-icons_f9bd01_256x240.png
  139. +410 −0 media/css/libs/jquery_ui/redmond/jquery-ui-1.8.14.datepicker.autocomplete.css
  140. +20 −0 media/css/mobile/mobile.css
  141. BIN media/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png
  142. BIN media/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png
  143. BIN media/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png
  144. BIN media/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png
  145. BIN media/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png
  146. BIN media/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
  147. BIN media/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
  148. BIN media/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
  149. BIN media/css/redmond/images/ui-icons_217bc0_256x240.png
  150. BIN media/css/redmond/images/ui-icons_2e83ff_256x240.png
  151. BIN media/css/redmond/images/ui-icons_469bdd_256x240.png
  152. BIN media/css/redmond/images/ui-icons_6da8d5_256x240.png
  153. BIN media/css/redmond/images/ui-icons_cd0a0a_256x240.png
  154. BIN media/css/redmond/images/ui-icons_d8e7f3_256x240.png
  155. BIN media/css/redmond/images/ui-icons_f9bd01_256x240.png
  156. +406 −0 media/css/redmond/jquery-ui-1.7.2.custom.css
  157. +326 −0 media/css/style.css
  158. BIN media/css/ui-darkness/images/ui-bg_flat_30_cccccc_40x100.png
  159. BIN media/css/ui-darkness/images/ui-bg_flat_50_5c5c5c_40x100.png
  160. BIN media/css/ui-darkness/images/ui-bg_glass_20_555555_1x400.png
  161. BIN media/css/ui-darkness/images/ui-bg_glass_40_0078a3_1x400.png
  162. BIN media/css/ui-darkness/images/ui-bg_glass_40_ffc73d_1x400.png
  163. BIN media/css/ui-darkness/images/ui-bg_gloss-wave_25_333333_500x100.png
  164. BIN media/css/ui-darkness/images/ui-bg_highlight-soft_80_eeeeee_1x100.png
  165. BIN media/css/ui-darkness/images/ui-bg_inset-soft_25_000000_1x100.png
  166. BIN media/css/ui-darkness/images/ui-bg_inset-soft_30_f58400_1x100.png
  167. BIN media/css/ui-darkness/images/ui-icons_222222_256x240.png
  168. BIN media/css/ui-darkness/images/ui-icons_4b8e0b_256x240.png
  169. BIN media/css/ui-darkness/images/ui-icons_a83300_256x240.png
  170. BIN media/css/ui-darkness/images/ui-icons_cccccc_256x240.png
  171. BIN media/css/ui-darkness/images/ui-icons_ffffff_256x240.png
  172. +406 −0 media/css/ui-darkness/jquery-ui-1.7.2.custom.css
  173. BIN media/img/blank.gif
  174. BIN media/img/calendar-icon.png
  175. BIN media/img/favicon.ico
  176. BIN media/img/particles.gif
  177. +47 −0 media/js/dates/emails_sent.js
  178. +137 −0 media/js/dates/following.js
  179. +63 −0 media/js/dates/home.js
  180. +33 −0 media/js/dates/hours.js
  181. +155 −0 media/js/dates/list.js
  182. +178 −0 media/js/dates/notify.js
  183. +12 −0 media/js/global.js
  184. BIN media/js/libs/audio/boom1.mp3
  185. BIN media/js/libs/audio/boom2.mp3
  186. BIN media/js/libs/audio/boom3.mp3
  187. BIN media/js/libs/audio/boom4.mp3
  188. BIN media/js/libs/audio/pop1.mp3
  189. BIN media/js/libs/audio/pop2.mp3
  190. BIN media/js/libs/audio/pop3.mp3
  191. BIN media/js/libs/audio/pop4.mp3
  192. BIN media/js/libs/audio/pop5.mp3
  193. BIN media/js/libs/audio/pop6.mp3
  194. +104 −0 media/js/libs/date.js
  195. +616 −0 media/js/libs/fireworks.js
  196. +5,208 −0 media/js/libs/fullcalendar.js
  197. +113 −0 media/js/libs/fullcalendar.min.js
  198. +0 −167 media/js/libs/jquery-1.4.4.min.js
  199. +18 −0 media/js/libs/jquery-1.6.2.min.js
  200. +4 −0 media/js/libs/jquery-1.6.4.min.js
  201. +4 −0 media/js/libs/jquery-1.7.1.min.js
  202. +164 −0 media/js/libs/jquery-ui-1.8.14.datepicker.autocomplete.min.js
  203. +10 −0 media/js/libs/jquery.cookie.min.js
  204. +7,347 −0 media/js/libs/jquery.dataTables.js
  205. +151 −0 media/js/libs/jquery.dataTables.min.js
  206. +6,937 −0 media/js/libs/jquery.mobile-1.0rc3.js
  207. +171 −0 media/js/libs/jquery.mobile-1.0rc3.min.js
  208. +0 −8,970 media/js/libs/jquery.ui.all.js
  209. +75 −0 media/js/libs/soundmanager2-nodebug-jsmin.js
  210. BIN media/js/libs/swf/soundmanager2.swf
  211. BIN media/js/libs/swf/soundmanager2_flash9.swf
  212. +368 −0 media/js/mobile/mobile.js
  213. +5 −0 media/js/users/profile.js
  214. +2 −0 requirements/compiled.txt
  215. +4 −1 requirements/dev.txt
  216. +1 −0 requirements/prod.txt
  217. +0 −327 settings.py
  218. +6 −0 settings/__init__.py
  219. +401 −0 settings/base.py
  220. +54 −0 settings/local.py-dist
  221. 0 { → settings}/settings_local.py-dist
  222. +10 −0 settings_test.py
  223. +11 −0 templates/404.html
  224. +79 −0 templates/500.html
  225. +51 −12 templates/base.html
  226. +22 −9 urls.py
  227. +1 −1 vendor
  228. +1,260 −0 vendor-local/lib/python/memcache.py
  229. +86 −0 vendor-local/lib/python/vobject/__init__.py
  230. +1,139 −0 vendor-local/lib/python/vobject/base.py
  231. +164 −0 vendor-local/lib/python/vobject/behavior.py
  232. +84 −0 vendor-local/lib/python/vobject/change_tz.py
  233. +125 −0 vendor-local/lib/python/vobject/hcalendar.py
  234. +1,916 −0 vendor-local/lib/python/vobject/icalendar.py
  235. +219 −0 vendor-local/lib/python/vobject/ics_diff.py
  236. +301 −0 vendor-local/lib/python/vobject/vcard.py
  237. +156 −0 vendor-local/lib/python/vobject/win32tz.py
  238. BIN vendor-local/src/django-auth-ldap/.hg/00changelog.i
  239. +1 −0 vendor-local/src/django-auth-ldap/.hg/branch
  240. +2 −0 vendor-local/src/django-auth-ldap/.hg/cache/branchheads
  241. BIN vendor-local/src/django-auth-ldap/.hg/dirstate
  242. +2 −0 vendor-local/src/django-auth-ldap/.hg/hgrc
  243. +4 −0 vendor-local/src/django-auth-ldap/.hg/requires
  244. BIN vendor-local/src/django-auth-ldap/.hg/store/00changelog.i
  245. BIN vendor-local/src/django-auth-ldap/.hg/store/00manifest.i
  246. BIN vendor-local/src/django-auth-ldap/.hg/store/data/_m_a_n_i_f_e_s_t.i
  247. BIN vendor-local/src/django-auth-ldap/.hg/store/data/_m_a_n_i_f_e_s_t.in.i
  248. BIN vendor-local/src/django-auth-ldap/.hg/store/data/django__auth__ldap/____init____.py.i
  249. BIN vendor-local/src/django-auth-ldap/.hg/store/data/django__auth__ldap/backend.py.i
  250. BIN vendor-local/src/django-auth-ldap/.hg/store/data/django__auth__ldap/config.py.i
  251. BIN vendor-local/src/django-auth-ldap/.hg/store/data/django__auth__ldap/dn.py.i
  252. BIN vendor-local/src/django-auth-ldap/.hg/store/data/django__auth__ldap/models.py.i
  253. BIN vendor-local/src/django-auth-ldap/.hg/store/data/django__auth__ldap/tests.py.i
  254. BIN vendor-local/src/django-auth-ldap/.hg/store/data/docs/_makefile.i
  255. BIN vendor-local/src/django-auth-ldap/.hg/store/data/docs/conf.py.i
  256. BIN vendor-local/src/django-auth-ldap/.hg/store/data/docs/index.rst.i
  257. BIN vendor-local/src/django-auth-ldap/.hg/store/data/setup.py.i
  258. BIN vendor-local/src/django-auth-ldap/.hg/store/data/tests/____init____.py.i
  259. BIN vendor-local/src/django-auth-ldap/.hg/store/data/tests/runtests.py.i
  260. BIN vendor-local/src/django-auth-ldap/.hg/store/data/tests/settings.py.i
  261. BIN vendor-local/src/django-auth-ldap/.hg/store/data/~2ehgignore.i
  262. BIN vendor-local/src/django-auth-ldap/.hg/store/data/~2ehgtags.i
  263. +17 −0 vendor-local/src/django-auth-ldap/.hg/store/fncache
  264. BIN vendor-local/src/django-auth-ldap/.hg/store/undo
  265. +1 −0 vendor-local/src/django-auth-ldap/.hg/undo.branch
  266. +3 −0 vendor-local/src/django-auth-ldap/.hg/undo.desc
  267. 0 vendor-local/src/django-auth-ldap/.hg/undo.dirstate
  268. +4 −0 vendor-local/src/django-auth-ldap/.hgignore
  269. +60 −0 vendor-local/src/django-auth-ldap/.hgtags
  270. +2 −0 vendor-local/src/django-auth-ldap/MANIFEST.in
  271. +24 −0 vendor-local/src/django-auth-ldap/django_auth_ldap.egg-info/PKG-INFO
  272. +14 −0 vendor-local/src/django-auth-ldap/django_auth_ldap.egg-info/SOURCES.txt
  273. +1 −0 vendor-local/src/django-auth-ldap/django_auth_ldap.egg-info/dependency_links.txt
  274. +1 −0 vendor-local/src/django-auth-ldap/django_auth_ldap.egg-info/top_level.txt
  275. 0 vendor-local/src/django-auth-ldap/django_auth_ldap/__init__.py
  276. +733 −0 vendor-local/src/django-auth-ldap/django_auth_ldap/backend.py
  277. +433 −0 vendor-local/src/django-auth-ldap/django_auth_ldap/config.py
  278. +32 −0 vendor-local/src/django-auth-ldap/django_auth_ldap/dn.py
  279. +10 −0 vendor-local/src/django-auth-ldap/django_auth_ldap/models.py
  280. +1,126 −0 vendor-local/src/django-auth-ldap/django_auth_ldap/tests.py
  281. +92 −0 vendor-local/src/django-auth-ldap/docs/Makefile
  282. +196 −0 vendor-local/src/django-auth-ldap/docs/conf.py
  283. +894 −0 vendor-local/src/django-auth-ldap/docs/index.rst
  284. +31 −0 vendor-local/src/django-auth-ldap/setup.py
  285. +5 −0 vendor-local/src/pip-delete-this-directory.txt
  286. +1 −0 vendor-local/src/python-dateutil
  287. +3 −0 vendor-local/vendor.pth
View
@@ -15,3 +15,8 @@ vendor
tmp/*
*~
*.mo
+settings/local*
+*.js.old
+TODO
+cover/
+sample_data.py
View
@@ -1,3 +1,6 @@
[submodule "vendor"]
path = vendor
url = git://github.com/mozilla/playdoh-lib.git
+[submodule "vendor-local/src/python-dateutil"]
+ path = vendor-local/src/python-dateutil
+ url = git://github.com/cozi/python-dateutil.git
View
@@ -1,51 +1,19 @@
-PTO Planner
-===========
+PTO
+===
-No more confusing math! This is a small web app (with a dumb name) to help
-you figure out how much PTO you'll have available on a given future date.
+Takes care of PTO management for Mozilla!
Install
=======
-To install, run:
+to be continued...
- pip install -r requirements/compiled.txt -r requirements/dev.txt
- cp settings_local.py-dist settings_local.py
- mysql -u root -e "create database pto_planner"
-
-Edit settings_local.py with the database credentials:
-
- 'NAME': 'pto_planner',
- 'USER': 'root',
- 'PASSWORD': '',
- ...
-
-Then start the web server:
-
- python manage.py runserver
-
-Begin Slacking Off
-==================
-
-Open http://localhost:8000/ and start planning your next vacation.
-
-Playdoh
-=======
-
-This site is built with Mozilla's Playdoh, a web application template
-based on [Django][django].
-
-Full [documentation][docs] for Playdoh is available.
-
-[django]: http://www.djangoproject.com/
-[gh-playdoh]: https://github.com/mozilla/playdoh
-[docs]: http://playdoh.rtfd.org/
License
-------
-This software is licensed under the [New BSD License][BSD]. For more
+This software is licensed under the [Mozilla Public License Version 1.1][MPL]. For more
information, read the file ``LICENSE``.
-[BSD]: http://creativecommons.org/licenses/BSD/
+[MPL]: http://www.mozilla.org/MPL/
@@ -0,0 +1 @@
+#
@@ -0,0 +1 @@
+# hey! I'm an app!
View
@@ -0,0 +1,210 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Sheriff Duty.
+#
+# The Initial Developer of the Original Code is Mozilla Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Peter Bengtsson, <peterbe@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+import ldap
+from django.conf import settings
+from django.core.urlresolvers import reverse
+from django.contrib.auth.models import User
+from django.utils import simplejson as json
+from users.utils.ldap_mock import MockLDAP
+from mock import Mock
+from nose.tools import eq_, ok_
+from test_utils import TestCase
+
+
+class CitiesTest(TestCase):
+
+ def test_cities(self):
+ url = reverse('autocomplete.cities')
+ response = self.client.get(url)
+ eq_(response.status_code, 403)
+
+ mortal = User.objects.create(username='mortal')
+ mortal.set_password('secret')
+ mortal.save()
+ assert self.client.login(username='mortal', password='secret')
+
+ response = self.client.get(url)
+ eq_(response.status_code, 200)
+ ok_(response['content-type'].startswith('application/json'))
+ struct = json.loads(response.content)
+ eq_(struct, [])
+
+ profile = mortal.get_profile()
+ profile.city = 'London'
+ profile.save()
+
+ response = self.client.get(url)
+ eq_(response.status_code, 200)
+ struct = json.loads(response.content)
+ eq_(struct, ['London'])
+
+ bob = User.objects.create(username='bob')
+ profile = bob.get_profile()
+ profile.city = 'Aberdeen'
+ profile.save()
+
+ response = self.client.get(url)
+ eq_(response.status_code, 200)
+ struct = json.loads(response.content)
+ eq_(struct, ['Aberdeen', 'London'])
+
+ response = self.client.get(url, {'term': 'LON'})
+ eq_(response.status_code, 200)
+ struct = json.loads(response.content)
+ eq_(struct, ['London'])
+
+
+class UsersTest(TestCase):
+
+ def setUp(self):
+ super(UsersTest, self).setUp()
+
+ ldap.open = Mock('ldap.open')
+ ldap.open.mock_returns = Mock('ldap_connection')
+ ldap.set_option = Mock(return_value=None)
+
+ def test_users(self):
+ results = [
+ ('mail=peter@mozilla.com,o=com,dc=mozilla',
+ {'cn': ['Peter Bengtsson'],
+ 'givenName': ['Pet\xc3\xa3r'], # utf-8 encoded
+ 'mail': ['peterbe@mozilla.com'],
+ 'sn': ['Bengtss\xc2\xa2n'],
+ 'uid': ['pbengtsson']
+ })
+ ]
+
+ ldap.initialize = Mock(return_value=MockLDAP({
+ '(&(objectClass=inetOrgPerson)(mail=*)(|(mail=peter*)(givenName=peter*)(sn=peter*)))': results
+ }))
+
+ url = reverse('autocomplete.users')
+ response = self.client.get(url, {'term': ' i '})
+ eq_(response.status_code, 403)
+
+ mortal = User.objects.create(
+ username='mortal',
+ first_name='Mortal',
+ last_name='Joe'
+ )
+ mortal.set_password('secret')
+ mortal.save()
+ assert self.client.login(username='mortal', password='secret')
+
+ response = self.client.get(url, {'term': ' i '})
+ eq_(response.status_code, 200)
+ ok_(response['content-type'].startswith('application/json'))
+
+ response = self.client.get(url, {'term': 'peter'})
+ eq_(response.status_code, 200)
+ ok_(response['content-type'].startswith('application/json'))
+ struct = json.loads(response.content)
+ ok_(isinstance(struct, list))
+ first_item = struct[0]
+
+ label = '%s %s <%s>' % (u'Pet\xe3r',
+ u'Bengtss\xa2n',
+ 'peterbe@mozilla.com')
+ value = label
+ eq_(first_item, {
+ 'id': 'pbengtsson',
+ 'label': label,
+ 'value': value,
+ })
+
+ def test_users_knownonly(self):
+ results = [
+ ('mail=peter@mozilla.com,o=com,dc=mozilla',
+ {'cn': ['Peter Bengtsson'],
+ 'givenName': ['Pet\xc3\xa3r'], # utf-8 encoded
+ 'mail': ['peterbe@mozilla.com'],
+ 'sn': ['Bengtss\xc2\xa2n'],
+ 'uid': ['pbengtsson']
+ }),
+ ('mail=peterino@mozilla.com,o=com,dc=mozilla',
+ {'cn': ['Peterino Gaudy'],
+ 'givenName': ['Pet\xc3\xa3rino'], # utf-8 encoded
+ 'mail': ['peterino@mozilla.com'],
+ 'sn': ['Gaudi'],
+ 'uid': ['peterino']
+ }),
+ ]
+
+ ldap.initialize = Mock(return_value=MockLDAP({
+ '(&(objectClass=inetOrgPerson)(mail=*)(|(mail=peter*)(givenName=peter*)(sn=peter*)))': results
+ }))
+
+ url = reverse('autocomplete.users_known_only')
+
+ mortal = User.objects.create(
+ username='mortal',
+ first_name='Mortal',
+ last_name='Joe'
+ )
+ mortal.set_password('secret')
+ mortal.save()
+ assert self.client.login(username='mortal', password='secret')
+
+ response = self.client.get(url, {'term': 'peter'})
+ eq_(response.status_code, 200)
+ ok_(response['content-type'].startswith('application/json'))
+ struct = json.loads(response.content)
+ ok_(isinstance(struct, list))
+ eq_(len(struct), 0)
+
+ User.objects.create(
+ username=results[0][1]['uid'],
+ email=results[0][1]['mail'].upper(),
+ first_name=results[0][1]['givenName'],
+ last_name=results[0][1]['sn'],
+ )
+ response = self.client.get(url, {'term': 'peter'})
+ eq_(response.status_code, 200)
+ struct = json.loads(response.content)
+ eq_(len(struct), 1)
+
+ first_item = struct[0]
+
+ label = '%s %s <%s>' % (u'Pet\xe3r',
+ u'Bengtss\xa2n',
+ 'peterbe@mozilla.com')
+ value = label
+ eq_(first_item, {
+ 'id': 'pbengtsson',
+ 'label': label,
+ 'value': value,
+ })
View
@@ -0,0 +1,46 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Sheriff Duty.
+#
+# The Initial Developer of the Original Code is Mozilla Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Peter Bengtsson, <peterbe@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+from django.conf.urls.defaults import patterns, url
+import views
+
+urlpatterns = patterns('',
+ url(r'^cities/$', views.cities, name='autocomplete.cities'),
+ url(r'^users/$', views.users, name='autocomplete.users'),
+ url(r'^users/knownonly/$', views.users,
+ {'known_only': True},
+ name='autocomplete.users_known_only'),
+)
Oops, something went wrong.

0 comments on commit 237e871

Please sign in to comment.