| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| import json |
| import os |
| from cStringIO import StringIO |
| import urllib2 |
| |
| import PIL |
| from tg import config |
| from nose.tools import assert_equal |
| from ming.orm.ormsession import ThreadLocalORMSession |
| from paste.httpexceptions import HTTPFound |
| |
| import allura |
| from allura import model as M |
| from allura.tests import TestController |
| from allura.tests import decorators as td |
| from allura.lib import helpers as h |
| |
| class TestNeighborhood(TestController): |
| |
| def setUp(self): |
| # change the override_root config value to change which root controller the test uses |
| self._make_app = allura.config.middleware.make_app |
| def make_app(global_conf, full_stack=True, **app_conf): |
| app_conf['override_root'] = 'basetest_neighborhood_root' |
| return self._make_app(global_conf, full_stack, **app_conf) |
| allura.config.middleware.make_app = make_app |
| super(TestNeighborhood, self).setUp() |
| |
| def tearDown(self): |
| super(TestNeighborhood, self).tearDown() |
| allura.config.middleware.make_app = self._make_app |
| |
| def test_home_project(self): |
| r = self.app.get('/adobe/wiki/') |
| assert r.location.endswith('/adobe/wiki/Home/') |
| r = r.follow() |
| assert 'This is the "Adobe" neighborhood' in str(r), str(r) |
| r = self.app.get('/adobe/admin/', extra_environ=dict(username='test-user'), |
| status=403) |
| |
| def test_redirect(self): |
| r = self.app.post('/adobe/_admin/update', |
| params=dict(redirect='wiki/Home/'), |
| extra_environ=dict(username='root')) |
| r = self.app.get('/adobe/') |
| assert r.location.endswith('/adobe/wiki/Home/') |
| |
| def test_admin(self): |
| r = self.app.get('/adobe/_admin/', extra_environ=dict(username='root')) |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| r = self.app.get('/adobe/_admin/accolades', extra_environ=dict(username='root')) |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.features['google_analytics'] = True |
| r = self.app.post('/adobe/_admin/update', |
| params=dict(name='Mozq1', css='', homepage='# MozQ1!', tracking_id='U-123456'), |
| extra_environ=dict(username='root')) |
| r = self.app.post('/adobe/_admin/update', |
| params=dict(name='Mozq1', css='', homepage='# MozQ1!\n[Root]'), |
| extra_environ=dict(username='root')) |
| # make sure project_template is validated as proper json |
| r = self.app.post('/adobe/_admin/update', |
| params=dict(project_template='{'), |
| extra_environ=dict(username='root')) |
| assert 'Invalid JSON' in r |
| |
| def test_admin_overview_audit_log(self): |
| |
| def check_log(message): |
| return M.AuditLog.query.find({'message': message}).count() == 1 |
| |
| nbhd = M.Neighborhood.query.get(name='Projects') |
| nbhd.features['css'] = 'custom' |
| nbhd.features['google_analytics'] = True |
| params = { |
| 'name': 'Pjs', |
| 'redirect': 'http://fake.org/', |
| 'show_title': 'false', |
| 'allow_browse': 'false', |
| 'css': '.class { border: 1px; }', |
| 'tracking_id': 'U-123456', |
| 'homepage': '[Homepage]', |
| 'project_list_url': 'http://fake.org/project_list', |
| 'project_template': '{"name": "template"}', |
| 'anchored_tools': 'wiki:Wiki' |
| |
| } |
| self.app.post('/p/_admin/update', params=params, |
| extra_environ=dict(username='root')) |
| # must get as many log records as many values are updated |
| assert M.AuditLog.query.find().count() == len(params) |
| |
| assert check_log('change neighborhood name to Pjs') |
| assert check_log('change neighborhood redirect to http://fake.org/') |
| assert check_log('change neighborhood show title to False') |
| assert check_log('change neighborhood allow browse to False') |
| assert check_log('change neighborhood css to .class { border: 1px; }') |
| assert check_log('change neighborhood homepage to [Homepage]') |
| assert check_log('change neighborhood project list url to ' |
| 'http://fake.org/project_list') |
| |
| assert check_log('change neighborhood project template to ' |
| '{"name": "template"}') |
| assert check_log('update neighborhood tracking_id') |
| |
| @td.with_wiki |
| def test_anchored_tools(self): |
| neighborhood = M.Neighborhood.query.get(name='Projects') |
| |
| r = self.app.post('/p/_admin/update', |
| params=dict(name='Projects', |
| anchored_tools='wiki:Wiki, tickets:Ticket'), |
| extra_environ=dict(username='root')) |
| assert 'error' not in self.webflash(r) |
| r = self.app.post('/p/_admin/update', |
| params=dict(name='Projects', |
| anchored_tools='w!iki:Wiki, tickets:Ticket'), |
| extra_environ=dict(username='root')) |
| assert 'error' in self.webflash(r) |
| assert_equal(neighborhood.anchored_tools, 'wiki:Wiki, tickets:Ticket') |
| |
| r = self.app.post('/p/_admin/update', |
| params=dict(name='Projects', |
| anchored_tools='wiki:Wiki,'), |
| extra_environ=dict(username='root')) |
| assert 'error' in self.webflash(r) |
| assert_equal(neighborhood.anchored_tools, 'wiki:Wiki, tickets:Ticket') |
| |
| r = self.app.post('/p/_admin/update', |
| params=dict(name='Projects', |
| anchored_tools='badname,'), |
| extra_environ=dict(username='root')) |
| assert 'error' in self.webflash(r) |
| assert_equal(neighborhood.anchored_tools, 'wiki:Wiki, tickets:Ticket') |
| |
| r = self.app.get('/p/test/admin/overview') |
| top_nav = r.html.find(id='top_nav') |
| assert top_nav.find(href='/p/test/wiki/'), top_nav |
| assert top_nav.find(href='/p/test/tickets/'), top_nav |
| |
| r = self.app.get('/p/test/admin/tools') |
| assert '<div class="fleft isnt_sorted">' in r |
| delete_tool = r.html.find('a', {'class':'mount_delete'}) |
| assert_equal(len(delete_tool), 1) |
| |
| def test_show_title(self): |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| # if not set show_title must be True |
| assert neighborhood.show_title |
| # title should be present |
| assert 'class="project_title"' in str(r) |
| r = self.app.post('/adobe/_admin/update', |
| params=dict(name='Mozq1', css='', |
| homepage='# MozQ1!', |
| tracking_id='U-123456', |
| show_title='false'), |
| extra_environ=dict(username='root')) |
| # no title now |
| r = self.app.get('/adobe/', extra_environ=dict(username='root')) |
| assert 'class="project_title"' not in str(r) |
| r = self.app.get('/adobe/wiki/Home/', |
| extra_environ=dict(username='root')) |
| assert 'class="project_title"' not in str(r) |
| |
| # title must be present on project page |
| r = self.app.get('/adobe/adobe-1/admin/', |
| extra_environ=dict(username='root')) |
| assert 'class="project_title"' in str(r) |
| |
| |
| def test_admin_stats_del_count(self): |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| proj = M.Project.query.get(neighborhood_id=neighborhood._id) |
| proj.deleted = True |
| ThreadLocalORMSession.flush_all() |
| r = self.app.get('/adobe/_admin/stats/', extra_environ=dict(username='root')) |
| assert 'Deleted: 1' in r |
| assert 'Private: 0' in r |
| |
| def test_admin_stats_priv_count(self): |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| proj = M.Project.query.get(neighborhood_id=neighborhood._id) |
| proj.deleted = False |
| proj.private = True |
| ThreadLocalORMSession.flush_all() |
| r = self.app.get('/adobe/_admin/stats/', extra_environ=dict(username='root')) |
| assert 'Deleted: 0' in r |
| assert 'Private: 1' in r |
| |
| def test_admin_stats_adminlist(self): |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| proj = M.Project.query.get(neighborhood_id=neighborhood._id) |
| proj.private = False |
| ThreadLocalORMSession.flush_all() |
| r = self.app.get('/adobe/_admin/stats/adminlist', extra_environ=dict(username='root')) |
| pq = M.Project.query.find(dict(neighborhood_id=neighborhood._id, deleted=False)) |
| pq.sort('name') |
| projects = pq.skip(0).limit(int(25)).all() |
| for proj in projects: |
| admin_role = M.ProjectRole.query.get(project_id=proj.root_project._id, name='Admin') |
| if admin_role is None: |
| continue |
| user_role_list = M.ProjectRole.query.find(dict(project_id=proj.root_project._id, name=None)).all() |
| for ur in user_role_list: |
| if ur.user is not None and admin_role._id in ur.roles: |
| assert proj.name in r |
| assert ur.user.username in r |
| |
| def test_icon(self): |
| file_name = 'neo-icon-set-454545-256x350.png' |
| file_path = os.path.join(allura.__path__[0], 'nf', 'allura', 'images', file_name) |
| file_data = file(file_path).read() |
| upload = ('icon', file_name, file_data) |
| |
| r = self.app.get('/adobe/_admin/', extra_environ=dict(username='root')) |
| r = self.app.post('/adobe/_admin/update', |
| params=dict(name='Mozq1', css='', homepage='# MozQ1'), |
| extra_environ=dict(username='root'), upload_files=[upload]) |
| r = self.app.get('/adobe/icon') |
| image = PIL.Image.open(StringIO(r.body)) |
| assert image.size == (48, 48) |
| |
| r = self.app.get('/adobe/icon?foo=bar') |
| |
| def test_google_analytics(self): |
| # analytics allowed |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.features['google_analytics'] = True |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| assert 'Analytics Tracking ID' in r |
| r = self.app.get('/adobe/adobe-1/admin/overview', extra_environ=dict(username='root')) |
| assert 'Analytics Tracking ID' in r |
| r = self.app.post('/adobe/_admin/update', |
| params=dict(name='Adobe', css='', homepage='# MozQ1', tracking_id='U-123456'), |
| extra_environ=dict(username='root')) |
| r = self.app.post('/adobe/adobe-1/admin/update', |
| params=dict(tracking_id='U-654321'), |
| extra_environ=dict(username='root')) |
| r = self.app.get('/adobe/adobe-1/admin/overview', extra_environ=dict(username='root')) |
| assert "_add_tracking('nbhd', 'U-123456');" in r |
| assert "_add_tracking('proj', 'U-654321');" in r |
| # analytics not allowed |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.features['google_analytics'] = False |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| assert 'Analytics Tracking ID' not in r |
| r = self.app.get('/adobe/adobe-1/admin/overview', extra_environ=dict(username='root')) |
| assert 'Analytics Tracking ID' not in r |
| r = self.app.get('/adobe/adobe-1/admin/overview', extra_environ=dict(username='root')) |
| assert "_add_tracking('nbhd', 'U-123456');" not in r |
| assert "_add_tracking('proj', 'U-654321');" not in r |
| |
| def test_custom_css(self): |
| test_css = '.test{color:red;}' |
| custom_css = 'Custom CSS' |
| |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.css = test_css |
| neighborhood.features['css'] = 'none' |
| r = self.app.get('/adobe/') |
| assert test_css not in r |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| assert custom_css not in r |
| |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.features['css'] = 'picker' |
| r = self.app.get('/adobe/') |
| while isinstance(r.response, HTTPFound): |
| r = r.follow() |
| assert test_css in r |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| assert custom_css in r |
| |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.features['css'] = 'custom' |
| r = self.app.get('/adobe/') |
| while isinstance(r.response, HTTPFound): |
| r = r.follow() |
| assert test_css in r |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| assert custom_css in r |
| |
| def test_picker_css(self): |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.features['css'] = 'picker' |
| |
| r = self.app.get('/adobe/_admin/overview', extra_environ=dict(username='root')) |
| assert 'Project title, font' in r |
| assert 'Project title, color' in r |
| assert 'Bar on top' in r |
| assert 'Title bar, background' in r |
| assert 'Title bar, foreground' in r |
| |
| r = self.app.post('/adobe/_admin/update', |
| params={'name': 'Adobe', |
| 'css': '', |
| 'homepage': '', |
| 'css-projecttitlefont': 'arial,sans-serif', |
| 'css-projecttitlecolor': 'green', |
| 'css-barontop': '#555555', |
| 'css-titlebarbackground': '#333', |
| 'css-titlebarcolor': '#444', |
| 'css-addopt-icon-theme': 'dark'}, |
| extra_environ=dict(username='root'), upload_files=[]) |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| assert '/*projecttitlefont*/.project_title{font-family:arial,sans-serif;}' in neighborhood.css |
| assert '/*projecttitlecolor*/.project_title{color:green;}' in neighborhood.css |
| assert '/*barontop*/.pad h2.colored {background-color:#555555; background-image: none;}' in neighborhood.css |
| assert '/*titlebarbackground*/.pad h2.title{background-color:#333; background-image: none;}' in neighborhood.css |
| assert "/*titlebarcolor*/.pad h2.title, .pad h2.title small a {color:#444;} "\ |
| ".pad h2.dark small b.ico {background-image: "\ |
| "url('/nf/_ew_/theme/allura/images/neo-icon-set-ffffff-256x350.png');}" in neighborhood.css |
| |
| def test_max_projects(self): |
| # Set max value to unlimit |
| neighborhood = M.Neighborhood.query.get(name='Projects') |
| neighborhood.features['max_projects'] = None |
| r = self.app.post('/p/register', |
| params=dict(project_unixname='maxproject1', project_name='Max project1', project_description='', neighborhood='Projects'), |
| antispam=True, |
| extra_environ=dict(username='root'), status=302) |
| assert '/p/maxproject1/admin' in r.location |
| |
| # Set max value to 0 |
| neighborhood = M.Neighborhood.query.get(name='Projects') |
| neighborhood.features['max_projects'] = 0 |
| r = self.app.post('/p/register', |
| params=dict(project_unixname='maxproject2', project_name='Max project2', project_description='', neighborhood='Projects'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| while isinstance(r.response, HTTPFound): |
| r = r.follow() |
| assert 'You have exceeded the maximum number of projects' in r |
| |
| def test_project_rate_limit(self): |
| # Set rate limit to unlimit |
| with h.push_config(config, **{'project.rate_limits': '{}'}): |
| r = self.app.post('/p/register', |
| params=dict(project_unixname='rateproject1', project_name='Rate project1', project_description='', neighborhood='Projects'), |
| antispam=True, |
| extra_environ=dict(username='test-user-1'), status=302) |
| assert '/p/rateproject1/admin' in r.location |
| |
| # Set rate limit to 1 in first hour of user account |
| with h.push_config(config, **{'project.rate_limits': '{"3600": 1}'}): |
| r = self.app.post('/p/register', |
| params=dict(project_unixname='rateproject2', project_name='Rate project2', project_description='', neighborhood='Projects'), |
| antispam=True, |
| extra_environ=dict(username='test-user-1')) |
| while isinstance(r.response, HTTPFound): |
| r = r.follow() |
| assert 'Project creation rate limit exceeded. Please try again later.' in r |
| |
| def test_project_rate_limit_admin(self): |
| # Set rate limit to unlimit |
| with h.push_config(config, **{'project.rate_limits': '{}'}): |
| r = self.app.post('/p/register', |
| params=dict(project_unixname='rateproject1', project_name='Rate project1', project_description='', neighborhood='Projects'), |
| antispam=True, |
| extra_environ=dict(username='root'), status=302) |
| assert '/p/rateproject1/admin' in r.location |
| |
| # Set rate limit to 1 in first hour of user account |
| with h.push_config(config, **{'project.rate_limits': '{"3600": 1}'}): |
| r = self.app.post('/p/register', |
| params=dict(project_unixname='rateproject2', project_name='Rate project2', project_description='', neighborhood='Projects'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| assert '/p/rateproject2/admin' in r.location |
| |
| def test_invite(self): |
| p_nbhd_id = str(M.Neighborhood.query.get(name='Projects')._id) |
| r = self.app.get('/adobe/_moderate/', extra_environ=dict(username='root')) |
| r = self.app.post('/adobe/_moderate/invite', |
| params=dict(pid='adobe-1', invite='on', neighborhood_id=p_nbhd_id), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'error' in r |
| r = self.app.post('/adobe/_moderate/invite', |
| params=dict(pid='no_such_user', invite='on', neighborhood_id=p_nbhd_id), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'error' in r |
| r = self.app.post('/adobe/_moderate/invite', |
| params=dict(pid='test', invite='on', neighborhood_id=p_nbhd_id), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'invited' in r, r |
| assert 'warning' not in r |
| r = self.app.post('/adobe/_moderate/invite', |
| params=dict(pid='test', invite='on', neighborhood_id=p_nbhd_id), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'warning' in r |
| r = self.app.post('/adobe/_moderate/invite', |
| params=dict(pid='test', uninvite='on', neighborhood_id=p_nbhd_id), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'uninvited' in r |
| assert 'warning' not in r |
| r = self.app.post('/adobe/_moderate/invite', |
| params=dict(pid='test', uninvite='on', neighborhood_id=p_nbhd_id), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'warning' in r |
| r = self.app.post('/adobe/_moderate/invite', |
| params=dict(pid='test', invite='on', neighborhood_id=p_nbhd_id), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'invited' in r |
| assert 'warning' not in r |
| |
| def test_evict(self): |
| r = self.app.get('/adobe/_moderate/', extra_environ=dict(username='root')) |
| r = self.app.post('/adobe/_moderate/evict', |
| params=dict(pid='test'), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'error' in r |
| r = self.app.post('/adobe/_moderate/evict', |
| params=dict(pid='adobe-1'), |
| extra_environ=dict(username='root')) |
| r = self.app.get(r.location, extra_environ=dict(username='root')) |
| assert 'adobe-1 evicted to Projects' in r |
| |
| def test_home(self): |
| r = self.app.get('/adobe/') |
| |
| def test_register(self): |
| r = self.app.get('/adobe/register', status=405) |
| r = self.app.post('/adobe/register', |
| params=dict(project_unixname='', project_name='Nothing', project_description='', neighborhood='Adobe'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| assert r.html.find('div', {'class':'error'}).string == 'Please use only letters, numbers, and dashes 3-15 characters long.' |
| r = self.app.post('/adobe/register', |
| params=dict(project_unixname='mymoz', project_name='My Moz', project_description='', neighborhood='Adobe'), |
| antispam=True, |
| extra_environ=dict(username='*anonymous'), |
| status=302) |
| r = self.app.post('/adobe/register', |
| params=dict(project_unixname='foo.mymoz', project_name='My Moz', project_description='', neighborhood='Adobe'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| assert r.html.find('div', {'class':'error'}).string == 'Please use only letters, numbers, and dashes 3-15 characters long.' |
| r = self.app.post('/p/register', |
| params=dict(project_unixname='test', project_name='Tester', project_description='', neighborhood='Projects'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| assert r.html.find('div', {'class':'error'}).string == 'This project name is taken.' |
| r = self.app.post('/adobe/register', |
| params=dict(project_unixname='mymoz', project_name='My Moz', project_description='', neighborhood='Adobe'), |
| antispam=True, |
| extra_environ=dict(username='root'), |
| status=302) |
| |
| def test_register_private_fails_for_anon(self): |
| r = self.app.post( |
| '/p/register', |
| params=dict( |
| project_unixname='mymoz', |
| project_name='My Moz', |
| project_description='', |
| neighborhood='Projects', |
| private_project='on'), |
| antispam=True, |
| extra_environ=dict(username='*anonymous'), |
| status=302) |
| assert config.get('auth.login_url', '/auth/') in r.location, r.location |
| |
| def test_register_private_fails_for_non_admin(self): |
| self.app.post( |
| '/p/register', |
| params=dict( |
| project_unixname='mymoz', |
| project_name='My Moz', |
| project_description='', |
| neighborhood='Projects', |
| private_project='on'), |
| antispam=True, |
| extra_environ=dict(username='test-user'), |
| status=403) |
| |
| def test_register_private_fails_for_non_private_neighborhood(self): |
| # Turn off private |
| neighborhood = M.Neighborhood.query.get(name='Projects') |
| neighborhood.features['private_projects'] = False |
| r = self.app.get('/p/add_project', extra_environ=dict(username='root')) |
| assert 'private_project' not in r |
| |
| r = self.app.post( |
| '/p/register', |
| params=dict( |
| project_unixname='myprivate1', |
| project_name='My Priv1', |
| project_description='', |
| neighborhood='Projects', |
| private_project='on'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| flash_msg_cookie = urllib2.unquote(r.headers['Set-Cookie']) |
| assert 'Internal Error.' in flash_msg_cookie |
| |
| proj = M.Project.query.get(shortname='myprivate1', neighborhood_id=neighborhood._id) |
| assert proj is None |
| |
| # Turn on private |
| neighborhood = M.Neighborhood.query.get(name='Projects') |
| neighborhood.features['private_projects'] = True |
| r = self.app.get('/p/add_project', extra_environ=dict(username='root')) |
| assert 'private_project' in r |
| |
| self.app.post( |
| '/p/register', |
| params=dict( |
| project_unixname='myprivate2', |
| project_name='My Priv2', |
| project_description='', |
| neighborhood='Projects', |
| private_project='on'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| |
| proj = M.Project.query.get(shortname='myprivate2', neighborhood_id=neighborhood._id) |
| assert proj.private |
| |
| def test_register_private_ok(self): |
| r = self.app.post( |
| '/p/register', |
| params=dict( |
| project_unixname='mymoz', |
| project_name='My Moz', |
| project_description='', |
| neighborhood='Projects', |
| private_project='on', |
| tools='wiki'), |
| antispam=True, |
| extra_environ=dict(username='root'), |
| status=302) |
| assert config.get('auth.login_url', '/auth/') not in r.location, r.location |
| r = self.app.get( |
| '/p/mymoz/wiki/', |
| extra_environ=dict(username='root')).follow(extra_environ=dict(username='root'), status=200) |
| r = self.app.get( |
| '/p/mymoz/wiki/', |
| extra_environ=dict(username='*anonymous'), |
| status=302) |
| assert config.get('auth.login_url', '/auth/') in r.location, r.location |
| self.app.get( |
| '/p/mymoz/wiki/', |
| extra_environ=dict(username='test-user'), |
| status=403) |
| |
| def test_project_template(self): |
| icon_url = 'file://' + os.path.join(allura.__path__[0], 'nf', 'allura', 'images', 'neo-icon-set-454545-256x350.png') |
| test_groups = [{ |
| "name": "Viewer", # group will be created, all params are valid |
| "permissions": ["read"], |
| "usernames": ["user01"] |
| }, { |
| "name": "", # group won't be created - invalid name |
| "permissions": ["read"], |
| "usernames": ["user01"] |
| }, { |
| "name": "TestGroup1", # group won't be created - invalid perm name |
| "permissions": ["foobar"], |
| "usernames": ["user01"] |
| }, { |
| "name": "TestGroup2", # will be created; 'inspect' perm ignored |
| "permissions": ["read", "inspect"], |
| "usernames": ["user01", "user02"] |
| }, { |
| "name": "TestGroup3", # will be created with no users in group |
| "permissions": ["admin"] |
| }] |
| r = self.app.post('/adobe/_admin/update', params=dict(name='Mozq1', |
| css='', homepage='# MozQ1!\n[Root]', project_template="""{ |
| "private":true, |
| "icon":{ |
| "url":"%s", |
| "filename":"icon.png" |
| }, |
| "tools":{ |
| "wiki":{ |
| "label":"Wiki", |
| "mount_point":"wiki", |
| "options":{ |
| "show_right_bar":false, |
| "show_left_bar":false, |
| "show_discussion":false, |
| "some_url": "http://foo.com/$shortname/" |
| }, |
| "home_text":"My home text!" |
| }, |
| "discussion":{"label":"Discussion","mount_point":"discussion"}, |
| "blog":{"label":"News","mount_point":"news","options":{ |
| "show_discussion":false |
| }}, |
| "admin":{"label":"Admin","mount_point":"admin"} |
| }, |
| "tool_order":["wiki","discussion","news","admin"], |
| "labels":["mmi"], |
| "trove_cats":{ |
| "topic":[247], |
| "developmentstatus":[11] |
| }, |
| "groups": %s |
| }""" % (icon_url, json.dumps(test_groups))), |
| extra_environ=dict(username='root')) |
| r = self.app.post( |
| '/adobe/register', |
| params=dict( |
| project_unixname='testtemp', |
| project_name='Test Template', |
| project_description='', |
| neighborhood='Mozq1', |
| private_project='off'), |
| antispam=True, |
| extra_environ=dict(username='root'), |
| status=302).follow() |
| p = M.Project.query.get(shortname='testtemp') |
| # make sure the correct tools got installed in the right order |
| top_nav = r.html.find('div', {'id':'top_nav'}) |
| assert top_nav.contents[1].contents[1].contents[1]['href'] == '/adobe/testtemp/wiki/' |
| assert 'Wiki' in top_nav.contents[1].contents[1].contents[1].contents[0] |
| assert top_nav.contents[1].contents[3].contents[1]['href'] == '/adobe/testtemp/discussion/' |
| assert 'Discussion' in top_nav.contents[1].contents[3].contents[1].contents[0] |
| assert top_nav.contents[1].contents[5].contents[1]['href'] == '/adobe/testtemp/news/' |
| assert 'News' in top_nav.contents[1].contents[5].contents[1].contents[0] |
| assert top_nav.contents[1].contents[7].contents[1]['href'] == '/adobe/testtemp/admin/' |
| assert 'Admin' in top_nav.contents[1].contents[7].contents[1].contents[0] |
| # make sure project is private |
| r = self.app.get( |
| '/adobe/testtemp/wiki/', |
| extra_environ=dict(username='root')).follow(extra_environ=dict(username='root'), status=200) |
| r = self.app.get( |
| '/adobe/testtemp/wiki/', |
| extra_environ=dict(username='*anonymous'), |
| status=302) |
| # check the labels and trove cats |
| r = self.app.get('/adobe/testtemp/admin/trove') |
| assert 'mmi' in r |
| assert 'Topic :: Communications :: Telephony' in r |
| assert 'Development Status :: 5 - Production/Stable' in r |
| # check the wiki text |
| r = self.app.get('/adobe/testtemp/wiki/').follow() |
| assert "My home text!" in r |
| # check tool options |
| opts = p.app_config('wiki').options |
| assert_equal(False, opts.show_discussion) |
| assert_equal(False, opts.show_left_bar) |
| assert_equal(False, opts.show_right_bar) |
| assert_equal("http://foo.com/testtemp/", opts.some_url) |
| # check that custom groups/perms/users were setup correctly |
| roles = p.named_roles |
| for group in test_groups: |
| name = group.get('name') |
| permissions = group.get('permissions', []) |
| usernames = group.get('usernames', []) |
| if name in ('Viewer', 'TestGroup2', 'TestGroup3'): |
| role = M.ProjectRole.by_name(name, project=p) |
| # confirm role created in project |
| assert role in roles |
| for perm in permissions: |
| # confirm valid permissions added to role, and invalid |
| # permissions ignored |
| if perm in p.permissions: |
| assert M.ACE.allow(role._id, perm) in p.acl |
| else: |
| assert M.ACE.allow(role._id, perm) not in p.acl |
| # confirm valid users received role |
| for username in usernames: |
| user = M.User.by_username(username) |
| if user and user._id: |
| assert role in user.project_role(project=p).roles |
| # confirm roles with invalid json data are not created |
| if name in ('', 'TestGroup1'): |
| assert name not in roles |
| |
| def test_projects_anchored_tools(self): |
| r = self.app.post('/adobe/_admin/update', params=dict(name='Adobe', |
| css='', |
| homepage='# Adobe!\n[Root]', |
| project_template="""{ |
| "private":true, |
| "tools":{ |
| "wiki":{ |
| "label":"Wiki", |
| "mount_point":"wiki", |
| "options":{ |
| "show_right_bar":false, |
| "show_left_bar":false, |
| "show_discussion":false, |
| "some_url": "http://foo.com/$shortname/" |
| }, |
| "home_text":"My home text!" |
| }, |
| "admin":{"label":"Admin","mount_point":"admin"} |
| }, |
| "tool_order":["wiki","admin"], |
| |
| }""" ), |
| extra_environ=dict(username='root')) |
| neighborhood = M.Neighborhood.query.get(name='Adobe') |
| neighborhood.anchored_tools ='wiki:Wiki' |
| r = self.app.post( |
| '/adobe/register', |
| params=dict( |
| project_unixname='testtemp', |
| project_name='Test Template', |
| project_description='', |
| neighborhood='Adobe', |
| private_project='off'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| r = self.app.get('/adobe/testtemp/admin/tools') |
| assert '<a href="/adobe/testtemp/wiki/" class="ui-icon-tool-wiki">' in r |
| assert '<a href="/adobe/testtemp/admin/" class="ui-icon-tool-admin">' in r |
| |
| def test_name_suggest(self): |
| r = self.app.get('/p/suggest_name?project_name=My+Moz') |
| assert_equal(r.json, dict(suggested_name='mymoz')) |
| r = self.app.get('/p/suggest_name?project_name=Te%st!') |
| assert_equal(r.json, dict(suggested_name='test')) |
| |
| def test_name_check(self): |
| for name in ('My+Moz', 'Te%st!', 'ab', 'a' * 16): |
| r = self.app.get('/p/check_names?neighborhood=Projects&project_unixname=%s' % name) |
| assert_equal(r.json, {'project_unixname': 'Please use only letters, numbers, and dashes 3-15 characters long.'}) |
| r = self.app.get('/p/check_names?neighborhood=Projects&project_unixname=mymoz') |
| assert_equal(r.json, {}) |
| r = self.app.get('/p/check_names?neighborhood=Projects&project_unixname=test') |
| assert_equal(r.json, {'project_unixname': 'This project name is taken.'}) |
| |
| @td.with_tool('test/sub1', 'Wiki', 'wiki') |
| def test_neighborhood_project(self): |
| self.app.get('/adobe/adobe-1/admin/', status=200) |
| self.app.get('/p/test/sub1/wiki/') |
| self.app.get('/p/test/sub1/', status=302) |
| self.app.get('/p/test/no-such-app/', status=404) |
| |
| def test_neighborhood_namespace(self): |
| # p/test exists, so try creating adobe/test |
| self.app.get('/adobe/test/wiki/', status=404) |
| r = self.app.post('/adobe/register', |
| params=dict(project_unixname='test', project_name='Test again', project_description='', neighborhood='Adobe', tools='wiki'), |
| antispam=True, |
| extra_environ=dict(username='root')) |
| assert r.status_int == 302, r.html.find('div', {'class':'error'}).string |
| r = self.app.get('/adobe/test/wiki/').follow(status=200) |
| |
| def test_neighborhood_awards(self): |
| file_name = 'adobe_icon.png' |
| file_path = os.path.join(allura.__path__[0], 'public', 'nf', 'images', file_name) |
| file_data = file(file_path).read() |
| upload = ('icon', file_name, file_data) |
| |
| r = self.app.get('/adobe/_admin/awards', extra_environ=dict(username='root')) |
| r = self.app.post('/adobe/_admin/awards/create', |
| params=dict(short='FOO', full='A basic foo award'), |
| extra_environ=dict(username='root'), upload_files=[upload]) |
| r = self.app.post('/adobe/_admin/awards/create', |
| params=dict(short='BAR', full='A basic bar award with no icon'), |
| extra_environ=dict(username='root')) |
| foo_id = str(M.Award.query.find(dict(short='FOO')).first()._id) |
| bar_id = str(M.Award.query.find(dict(short='BAR')).first()._id) |
| r = self.app.post('/adobe/_admin/awards/%s/update' % bar_id, |
| params=dict(short='BAR2', full='Updated description.'), |
| extra_environ=dict(username='root')).follow().follow() |
| assert 'BAR2' in r |
| assert 'Updated description.' in r |
| r = self.app.get('/adobe/_admin/awards/%s' % foo_id, extra_environ=dict(username='root')) |
| r = self.app.get('/adobe/_admin/awards/%s/icon' % foo_id, extra_environ=dict(username='root')) |
| image = PIL.Image.open(StringIO(r.body)) |
| assert image.size == (48, 48) |
| self.app.post('/adobe/_admin/awards/grant', |
| params=dict(grant='FOO', recipient='adobe-1'), |
| extra_environ=dict(username='root')) |
| self.app.get('/adobe/_admin/awards/%s/adobe-1' % foo_id, extra_environ=dict(username='root')) |
| self.app.post('/adobe/_admin/awards/%s/adobe-1/revoke' % foo_id, |
| extra_environ=dict(username='root')) |
| self.app.post('/adobe/_admin/awards/%s/delete' % foo_id, |
| extra_environ=dict(username='root')) |
| |
| def test_add_a_project_link(self): |
| from pylons import tmpl_context as c |
| # Install Home tool for all neighborhoods |
| for nb in M.Neighborhood.query.find().all(): |
| p = nb.neighborhood_project |
| with h.push_config(c, user=M.User.query.get()): |
| p.install_app('home', 'home', 'Home', ordinal=0) |
| r = self.app.get('/p/') |
| assert 'Add a Project' in r |
| r = self.app.get('/u/', extra_environ=dict(username='test-user')) |
| assert 'Add a Project' not in r |
| r = self.app.get('/adobe/', extra_environ=dict(username='test-user')) |
| assert 'Add a Project' not in r |
| r = self.app.get('/u/', extra_environ=dict(username='root')) |
| assert 'Add a Project' in r |
| r = self.app.get('/adobe/', extra_environ=dict(username='root')) |
| assert 'Add a Project' in r |
| |
| def test_help(self): |
| r = self.app.get('/p/_admin/help/', extra_environ=dict(username='root')) |
| assert 'macro' in r |
| |
| @td.with_user_project('test-user') |
| def test_profile_topnav_menu(self): |
| r = self.app.get('/u/test-user/', extra_environ=dict(username='test-user')).follow() |
| assert '<a href="/u/test-user/profile/" class="ui-icon-tool-profile">' in r, r |
| |
| def test_user_project_creates_on_demand(self): |
| M.User.register(dict(username='donald-duck'), make_project=False) |
| ThreadLocalORMSession.flush_all() |
| self.app.get('/u/donald-duck/') |
| |
| def test_disabled_user_has_no_user_project(self): |
| user = M.User.register(dict(username='donald-duck')) |
| self.app.get('/u/donald-duck/') # assert it's there |
| M.User.query.update(dict(username='donald-duck'), {'$set': {'disabled': True}}) |
| self.app.get('/u/donald-duck/', status=404) |
| |
| |
| def test_more_projects_link(self): |
| r = self.app.get('/adobe/adobe-1/admin/') |
| link = r.html.find('div', {'class':'neighborhood_title_link'}).find('a') |
| assert 'View More Projects' in str(link) |
| assert link['href'] == '/adobe/' |