diff --git a/app.py b/app.py index d559ed8..3722cbf 100644 --- a/app.py +++ b/app.py @@ -174,16 +174,16 @@ def build_rsvps_response(events): @app.route('/api/organizations') -@app.route('/api/organizations/') -def get_organizations(name=None): +@app.route('/api/organizations/') +def get_organizations(organization_name=None): ''' Regular response option for organizations. ''' filters, querystring = get_query_params(request.args) - if name: + if organization_name: # Get one named organization. - org_filter = Organization.name == raw_name(name) + org_filter = func.lower(Organization.name) == func.lower(raw_name(organization_name)) org = db.session.query(Organization).filter(org_filter).first() if org: return jsonify(org.asdict(True)) @@ -242,7 +242,7 @@ def get_orgs_events(organization_name): Better than /api/events?q={"filters":[{"name":"organization_name","op":"eq","val":"Code for San Francisco"}]} ''' # Check org name - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 @@ -258,7 +258,7 @@ def get_upcoming_events(organization_name): Get events that occur in the future. Order asc. ''' # Check org name - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 # Get upcoming event objects @@ -273,7 +273,7 @@ def get_past_events(organization_name): Get events that occur in the past. Order desc. ''' # Check org name - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 # Get past event objects @@ -287,7 +287,7 @@ def get_past_events(organization_name): def gather_orgs_rsvps(organization_name=None): ''' Orgs rsvps summarized ''' # Check org name - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 orgs_events = Event.query.filter(Event.organization_name == organization.name).all() @@ -302,7 +302,7 @@ def get_orgs_stories(organization_name): A cleaner url for getting an organizations stories ''' # Check org name - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 @@ -318,7 +318,7 @@ def get_orgs_projects(organization_name): A cleaner url for getting an organizations projects ''' # Check org name - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 @@ -378,7 +378,7 @@ def get_orgs_issues(organization_name, labels=None): ''' A clean url to get an organizations issues ''' # Get one named organization. - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 @@ -419,7 +419,7 @@ def get_orgs_attendance(organization_name): ''' A clean url to get an organizations attendance ''' # Get one named organization. - organization = Organization.query.filter_by(name=raw_name(organization_name)).first() + organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first() if not organization: return "Organization not found", 404 diff --git a/test/factories.py b/test/factories.py index 3d3e2a8..fc4a252 100644 --- a/test/factories.py +++ b/test/factories.py @@ -93,7 +93,7 @@ class AttendanceFactory(SQLAlchemyModelFactory): FACTORY_SESSION = db.session organization_name = factory.LazyAttribute(lambda e: OrganizationFactory().name) - organization_url = "https://www.codeforamerica.org/api/organizations/" + str(factory.LazyAttribute(lambda e: OrganizationFactory().name)).replace(" ", "-") + organization_url = u"https://www.codeforamerica.org/api/organizations/" + unicode(factory.LazyAttribute(lambda e: OrganizationFactory().name)).replace(u" ", u"-") total = randint(1, 1000) weekly = { "2014 01": randint(1, 50), diff --git a/test/integration/test_organizations.py b/test/integration/test_organizations.py index 33866e9..c8f2fa9 100644 --- a/test/integration/test_organizations.py +++ b/test/integration/test_organizations.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta import time -from test.factories import OrganizationFactory, ProjectFactory, EventFactory, StoryFactory, IssueFactory, LabelFactory +from test.factories import OrganizationFactory, ProjectFactory, EventFactory, StoryFactory, IssueFactory, LabelFactory, AttendanceFactory from test.harness import IntegrationTest from app import db @@ -644,4 +644,97 @@ def test_geojson(self): self.assertTrue('id' in org.keys()) # Test that only orgs with location data showed up - self.assertEqual(len(response['features']),1) + self.assertEqual(len(response['features']), 1) + + def test_organization_parameters_case_insensitive(self): + ''' Parameters passed via the URL should be case-insensitive. + ''' + cfsf = OrganizationFactory(name=u'Code for San Francisco') + db.session.commit() + + # request the organization + response = self.app.get('/api/organizations/code-for-san-francisco') + response_data = json.loads(response.data) + self.assertEqual(200, response.status_code) + self.assertTrue('name' in response_data) + self.assertEqual(u'Code for San Francisco', response_data['name']) + + # add some events + EventFactory(organization_name=cfsf.name, name=u'Umoja', start_time_notz=datetime.now() - timedelta(3)) + EventFactory(organization_name=cfsf.name, name=u'Kujichagulia', start_time_notz=datetime.now() - timedelta(2)) + EventFactory(organization_name=cfsf.name, name=u'Ujima', start_time_notz=datetime.now() - timedelta(1)) + EventFactory(organization_name=cfsf.name, name=u'Nia', start_time_notz=datetime.now() + timedelta(1)) + EventFactory(organization_name=cfsf.name, name=u'Kuumba', start_time_notz=datetime.now() + timedelta(2)) + db.session.commit() + + # request all the organization's events + response = self.app.get('/api/organizations/code-for-san-francisco/events') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertEqual(response_data['total'], 5) + + # request the organization's upcoming events + response = self.app.get('/api/organizations/code-for-san-francisco/upcoming_events') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertEqual(response_data['total'], 2) + + # request the organization's past events + response = self.app.get('/api/organizations/code-for-san-francisco/past_events') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertEqual(response_data['total'], 3) + + # request the organization's rsvps + response = self.app.get('/api/organizations/code-for-san-francisco/events/rsvps') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertEqual(response_data['total'], 3702) + + # add a story + StoryFactory(organization_name=cfsf.name) + db.session.commit() + + response = self.app.get('/api/organizations/code-for-san-francisco/stories') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertEqual(response_data['total'], 1) + + # add some projects + project_mkeka = ProjectFactory(organization_name=cfsf.name, name=u'Mkeka') + project_mahindi = ProjectFactory(organization_name=cfsf.name, name=u'Mahindi') + db.session.commit() + + response = self.app.get('/api/organizations/code-for-san-francisco/projects') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertEqual(response_data['total'], 2) + + # add some issues + IssueFactory(project_id=project_mkeka.id, title=u'Mishumaa Saba') + IssueFactory(project_id=project_mkeka.id, title=u'Kikombe cha Umoja') + IssueFactory(project_id=project_mahindi.id, title=u'Zawadi') + db.session.commit() + + response = self.app.get('/api/organizations/code-for-san-francisco/issues') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertEqual(response_data['total'], 3) + + # add some attendance + AttendanceFactory(organization_name=cfsf.name) + db.session.commit() + + response = self.app.get('/api/organizations/code-for-san-francisco/attendance') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.data) + self.assertTrue('total' in response_data) + self.assertTrue('organization_name' in response_data) + self.assertEqual(response_data['organization_name'], cfsf.name)