def test_delete(self): # Requires login: res = self.test_client.post("/goals/delete/", data={'id': 0}) setup.assertRequiresLogin(self, res) self.login() ## Validates form: res = self.test_client.post("/goals/delete/", data={'foo': 'bar'}) setup.assertInvalid(self, res, "id") ## works at all new_goal = self.create_test_goal() res = self.test_client.post("/goals/delete/", data={'id': new_goal['id']}) setup.assertOk(self, res, 204) ## 404s res = self.test_client.post("/goals/delete/", data={'id': new_goal['id']}) setup.assert404(self, res) ## Can't someone *else*'s goal. new_goal = self.create_test_goal() self.logout() self.login_other_user() res = self.test_client.post("/goals/delete/", data={'id': new_goal['id']}) setup.assertInvalidCredentials(self, res)
def test_get(self): tc = self.test_client ## Login required setup.assertRequiresLogin(self, tc.get("/goals/0/check-ins/0/")) ## Goal exists self.login() setup.assert404(self, tc.get("/goals/0/check-ins/0/")) ## user is goal owner goal = self.create_test_numeric_goal() goal_id = str(goal.get_id()) self.logout() self.login_other_user() setup.assertInvalidCredentials( self, tc.get("/goals/" + goal_id + "/check-ins/0/")) ## Check in must exist self.logout() self.login() setup.assert404(self, tc.get("/goals/" + goal_id + "/check-ins/0/")) ## Returns correctly ci = CheckIn( goal, Timeframe.get_current_timeframe(goal.check_in_frequency_name), 1) ci.persist() tfid = str(ci.timeframe) res = tc.get("/goals/" + goal_id + "/check-ins/" + tfid + "/") setup.assertOk(self, res, 200) self.assertEqual(json.loads(res.data), ci.to_dict())
def test_get(self): tc = self.test_client ## Login required setup.assertRequiresLogin(self, tc.get("/goals/0/check-ins/0/")) ## Goal exists self.login() setup.assert404(self, tc.get("/goals/0/check-ins/0/")) ## user is goal owner goal = self.create_test_numeric_goal() goal_id = str(goal.get_id()) self.logout() self.login_other_user() setup.assertInvalidCredentials(self, tc.get("/goals/" + goal_id + "/check-ins/0/")) ## Check in must exist self.logout() self.login() setup.assert404(self, tc.get("/goals/" + goal_id + "/check-ins/0/")) ## Returns correctly ci = CheckIn(goal, Timeframe.get_current_timeframe(goal.check_in_frequency_name), 1) ci.persist() tfid = str(ci.timeframe) res = tc.get("/goals/" + goal_id + "/check-ins/" + tfid + "/") setup.assertOk(self, res, 200) self.assertEqual(json.loads(res.data), ci.to_dict())
def test_register(self): tc = self.test_client invalid_user = {} for x, y in self.new_user.iteritems(): if x != 'password': invalid_user[x] = y res = tc.post('/register/', data=invalid_user) setup.assertInvalid(self, res, 'password') res = tc.post("/register/", data=self.new_user) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn('id', data) for field, value in self.new_user.iteritems(): if (field == 'password'): self.assertNotIn(field, data) else: self.assertEqual(value, data[field]) ## you should get a well-formatted error if the user already exists. self.new_user['password'] = "******" res = tc.post("/register/", data=self.new_user) self.assertEqual(res.status_code, 409) data = json.loads(res.data) self.assertIn('detail', data) self.assertIn('[email protected] already exists', data['detail']) self.new_user['password'] = "******"
def test_get_by_time(self): tc = self.test_client ## Login required setup.assertRequiresLogin(self, tc.get("/goals/0/check-ins/")) ## Goal must exist self.login() setup.assert404(self, tc.get("/goals/0/check-ins/")) ## User is the goal's owner goal = self.create_test_numeric_goal() goal_id = str(goal.get_id()) self.logout() self.login_other_user() setup.assertInvalidCredentials(self, tc.get("/goals/" + goal_id + "/check-ins/")) ## Start and end are present self.logout() self.login() setup.assertBadData(self, tc.get("/goals/" + goal_id + "/check-ins/"), "start and end") setup.assertBadData(self, tc.get("/goals/" + goal_id + "/check-ins/?start=banana"), "start and end") setup.assertBadData(self, tc.get("/goals/" + goal_id + "/check-ins/?end=banana"), "start and end") ## Start and end in format YYYY-MM-DD HH:mm:ss res = tc.get("/goals/" + goal_id + "/check-ins/?start=2016-01-01 10:00:00&end=banana") setup.assertBadData(self, res, "'banana' does not match format") res = tc.get("/goals/" + goal_id + "/check-ins/?start=strawberry&end=2016-01-01 10:00:00") setup.assertBadData(self, res, "'strawberry' does not match format") ## Returns empty for no check-ins res = tc.get("/goals/" + goal_id + "/check-ins/?start=2016-01-01 00:00:00&end=2016-01-08 00:00:00") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("check-ins", data) self.assertEqual(len(data['check-ins']), 0) ## Correctly returns multiple check-ins ci = CheckIn(goal, Timeframe(goal.check_in_frequency_name, datetime.datetime(2015, 12, 31)), 0) ci.persist() for x in range(0, 8): #one preceding and one postceding so we can make sure this limits the results tf = ci.timeframe_obj new_tf = Timeframe(tf.frequency_name, tf.start + datetime.timedelta(1)) ci = CheckIn(ci.goal_obj, new_tf, x) ci.persist() res = tc.get("/goals/" + goal_id + "/check-ins/?start=2016-01-01 00:00:00&end=2016-01-08 00:00:00") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("check-ins", data) self.assertEqual(len(data['check-ins']), 7) for index, check_in in enumerate(data['check-ins']): self.assertEqual(index, check_in['value'])
def test_update(self): tc = self.test_client res = tc.post('/register/', data=self.new_user) setup.assertOk(self, res, 201) user = json.loads(res.data) post_data = {"password": self.new_user['password'], "first_name": "new-first-name"} res = tc.post('/users/update/', data=post_data) setup.assertInvalid(self, res, 'email') post_data['email'] = "not-real-email" res = tc.post('/users/update/', data=post_data) setup.assertInvalidCredentials(self, res) post_data['email'] = self.new_user['email'] post_data['password'] = '******' res = tc.post('/users/update/', data=post_data) setup.assertInvalidCredentials(self, res) post_data['password'] = self.new_user['password'] res = tc.post('/users/update/', data=post_data) setup.assertOk(self, res) res = tc.post('/login/', data={'email': self.new_user['email'], 'password': self.new_user['password']}) setup.assertOk(self, res, 201) res = tc.get('/users/me/') setup.assertOk(self, res) updated_user = json.loads(res.data) for key, value in user.iteritems(): if (key == 'first_name'): self.assertEqual(updated_user[key], 'new-first-name') else: self.assertEqual(updated_user[key], user[key])
def test_create(self): # Requires login: res = self.test_client.post("/goals/create/", data=self.new_goal) setup.assertRequiresLogin(self, res) self.login() ## Test that it rejects bad inputs bad_goal = self.new_goal.copy() bad_goal['name'] = None res = self.test_client.post("/goals/create/", data=bad_goal) setup.assertInvalid(self, res, "name") bad_goal['name'] = self.new_goal['name'] bad_goal['prompt'] = "" res = self.test_client.post("/goals/create/", data=bad_goal) setup.assertBadData(self, res, "Prompt must be between 0 and 255 characters") ## Test that it actually registers at all :-) res = self.test_client.post("/goals/create/", data=self.new_goal) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn('id', data) goal = Goal.pull_by_id(data['id']) self.assertIsNotNone(goal) for key, val in self.new_goal.iteritems(): self.assertEqual(val, data[key]) if (key == 'frequency' or key == 'check_in_frequency'): self.assertEqual(val, Frequency.get_name_by_id(getattr(goal, key))) else: self.assertEqual(val, getattr(goal, key)) ## Shouldn't be able to register something that already exists res = self.test_client.post("/goals/create/", data=self.new_goal) self.assertEqual(res.status_code, 409) data = json.loads(res.data) self.assertIn('detail', data) self.assertIn('Test goal already exists', data['detail'])
def test_login(self): tc = self.test_client res = tc.post('/register/', data=self.new_user) res = tc.post('/login/', data={"email": self.new_user['email']}) setup.assertInvalid(self, res, 'password') res = tc.post('/login/', data={"email": "notreal", "password": self.new_user['password']}) data = json.loads(res.data) self.assertIn('detail', data) self.assertIn('notreal is not a registered', data['detail']) self.assertEqual(res.status_code, 401) res = tc.post('/login/', data={"email": self.new_user['email'], "password": "******"}) data = json.loads(res.data) self.assertIn('detail', data) self.assertIn('Incorrect password', data['detail']) self.assertEqual(res.status_code, 401) res = tc.post('/login/', data={"email": self.new_user['email'], "password": self.new_user['password']}) setup.assertOk(self, res, 201)
def test_destroy(self): user = User(self.new_user['email'], self.new_user['password'], self.new_user['first_name'], self.new_user['last_name']) user.persist() self.assertTrue(user.exists()) ## I don't understand why but this is necessary or else line 45 fails tc = self.test_client res = tc.post("/users/delete/", data={"email": "fake email"}) setup.assertInvalid(self, res, 'password') res = tc.post("/users/delete/", data={"email": "fake email", "password": "******"}) data = json.loads(res.data) setup.assertInvalidCredentials(self, res) self.assertTrue(user.exists()) tc = self.test_client res = tc.post("/users/delete/", data={"email": user.email, "password": "******"}) data = json.loads(res.data) setup.assertInvalidCredentials(self, res) self.assertTrue(user.exists()) res = tc.post("/users/delete/", data={"email": user.email, "password": "******"}) setup.assertOk(self, res, 204) self.assertFalse(user.exists())
def test_get_index(self): tc = self.test_client res = tc.get('/users/index/') setup.assertRequiresLogin(self, res) setup.create_test_users() res = tc.post('/login/', data={'email': "*****@*****.**", 'password': self.new_user['password']}) setup.assertOk(self, res, 201) res = tc.get('/users/index/') setup.assertOk(self, res) data = json.loads(res.data) self.assertIn('users', data) data = data['users'] self.assertEqual(len(data), 20) # default is 20 for x in range(ord('a'), ord('a') + 19): self.assertEqual(data[x - ord('a')]['email'], 'test_' + chr(x) + '@example.com') ## Should sort by email res = tc.get('/users/index/?count=3&offset=3') setup.assertOk(self, res) data = json.loads(res.data) self.assertIn('users', data) data = data['users'] self.assertEqual(len(data), 3) for x in range(ord('a'), ord('a') + 2): self.assertEqual(data[x - ord('a')]['email'], 'test_' + chr(x + 3) + '@example.com') ## Should still sort by email res = tc.get('/users/index/?count=3&offset=3&sort=last_name&sort_order=desc') setup.assertOk(self, res) data = json.loads(res.data) self.assertIn('users', data) data = data['users'] self.assertEqual(len(data), 3) for x in range(ord('a'), ord('a') + 2): self.assertEqual(data[x - ord('a')]['email'], 'test_' + chr(2 * ord('a') + 25 - x - 3) + '@example.com') res = tc.get('/users/index/?count=3&offset=3&sort=not_a_real_field&sort_order=desc') setup.assertInvalid(self, res, 'sort') res = tc.get('/users/index/?count=3&offset=3&sort=last_name&sort_order=pineapple') setup.assertInvalid(self, res, 'sort_order')
def test_get(self): ## Requires login res = self.test_client.get("/goals/0/") setup.assertRequiresLogin(self, res) ## 404s self.login() res = self.test_client.get("/goals/0/") setup.assert404(self, res) ## Can access own private goals goal = self.create_test_goal() res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertOk(self, res, 200) self.assertEqual(json.loads(res.data), goal) ## Cannot access other's private goals self.logout() self.login_other_user() res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertInvalidCredentials(self, res) ## Can access own public goals self.logout() self.login() res = self.test_client.post("/goals/update/", data={ 'id': goal['id'], 'public': True }) setup.assertOk(self, res) res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertOk(self, res, 200) goal['public'] = True self.assertEqual(json.loads(res.data), goal) ## Can access others' public goals self.logout() self.login_other_user() res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertOk(self, res, 200) self.assertEqual(json.loads(res.data), goal)
def test_get(self): ## Requires login res = self.test_client.get("/goals/0/") setup.assertRequiresLogin(self, res) ## 404s self.login() res = self.test_client.get("/goals/0/") setup.assert404(self, res) ## Can access own private goals goal = self.create_test_goal() res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertOk(self, res, 200) self.assertEqual(json.loads(res.data), goal) ## Cannot access other's private goals self.logout() self.login_other_user() res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertInvalidCredentials(self, res) ## Can access own public goals self.logout() self.login() res = self.test_client.post("/goals/update/", data={'id': goal['id'], 'public': True}) setup.assertOk(self, res) res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertOk(self, res, 200) goal['public'] = True self.assertEqual(json.loads(res.data), goal) ## Can access others' public goals self.logout() self.login_other_user() res = self.test_client.get('/goals/' + str(goal['id']) + '/') setup.assertOk(self, res, 200) self.assertEqual(json.loads(res.data), goal)
def test_get_user(self): tc = self.test_client res = tc.get('/users/1/') setup.assertRequiresLogin(self, res) res = tc.post('/register/', data=self.new_user) setup.assertOk(self, res, 201) user_data = json.loads(res.data) res = tc.post('/login/', data={"email": self.new_user['email'], "password": self.new_user['password']}) setup.assertOk(self, res, 201) res = tc.get('/users/' + str(user_data['id']) + '/') setup.assertOk(self, res) self.assertEqual(user_data, json.loads(res.data)) res = tc.get('/users/0/') self.assertEqual(res.status_code, 404)
def test_update_password(self): tc = self.test_client res = tc.post("/register/", data=self.new_user) setup.assertOk(self, res, 201) ## Shoudl fail if missing a key res = tc.post('/users/update-password/', data={"email": self.new_user['email'], "new_password": "******"}) setup.assertInvalid(self, res, 'old_password') ## should fail for non-existent emails res = tc.post('/users/update-password/', data={"email": "notreal", "old_password": "******", "new_password": "******"}) setup.assertInvalidCredentials(self, res) res = tc.post('/users/update-password/', data={"email": self.new_user['email'], "old_password": "******", "new_password": "******"}) setup.assertInvalidCredentials(self, res) res = tc.post('/users/update-password/', data={"email": self.new_user['email'], "old_password": self.new_user['password'], "new_password": "******"}) setup.assertOk(self, res) res = tc.post("/login/", data={"email": self.new_user['email'], "password": "******"}) setup.assertOk(self, res, 201)
def test_get_me(self): tc = self.test_client res = tc.get('/users/me/') ## Should return anonymous user setup.assertRequiresLogin(self, res) res = tc.post('/register/', data=self.new_user) setup.assertOk(self, res, 201) data = json.loads(res.data) res = tc.post('/login/', data={"email": self.new_user['email'], "password": self.new_user['password']}) setup.assertOk(self, res, 201) res = tc.get('/users/me/') setup.assertOk(self, res) for key in ["registered_on", "first_name", "last_name", "id", "email"]: self.assertIn(key, data) if (key in self.new_user): self.assertEqual(self.new_user[key], data[key]) res = tc.post('/logout/') res = tc.get('/users/me/') ## Should return anonymous user setup.assertRequiresLogin(self, res)
def test_update_email(self): tc = self.test_client post_data = {"old_email": self.new_user['email'], "new_email": "*****@*****.**", "password": self.new_user['password']} res = tc.post('/users/update-email/', data=post_data) setup.assertInvalidCredentials(self, res) res = tc.post('/register/', data=self.new_user) setup.assertOk(self, res, 201) post_data['password'] = '******' res = tc.post('/users/update-email/', data=post_data) setup.assertInvalidCredentials(self, res) post_data['password'] = None res = tc.post('/users/update-email/', data=post_data) setup.assertInvalid(self, res, 'password') post_data['password'] = self.new_user['password'] res = tc.post('/users/update-email/', data=post_data) setup.assertOk(self, res) res = tc.post('/login/', data={"email": post_data['new_email'], "password": post_data['password']}) setup.assertOk(self, res, 201)
def logout(self): return setup.assertOk(self, setup.logout(), 204)
def login(self): return setup.assertOk(self, setup.login_test_user(), 201)
def test_index(self): ## Requires login res = self.test_client.get("/goals/users/0/") setup.assertRequiresLogin(self, res) ## 404s on bum user self.login() res = self.test_client.get("/goals/users/0/") setup.assert404(self, res) # Empty if user has no goals user_id = str(json.loads(self.test_client.get("/users/me/").data)['id']) res = self.test_client.get("/goals/users/" + user_id +"/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 0) ## Shows only public goals even for current user setup.create_test_goals() res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 0) # No public goals public_goals = db.session.query(Goal).all() for goal in public_goals: goal.update({"public": True}) res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 name_appendix = ord('a') is_public = False ## Test to make sure at least one is public is_private = False # none should be private for goal in data['goals']: if (goal['public']): is_public = True else: is_private = True self.assertTrue(goal['active']) # by default they're all active self.assertEqual(goal['name'], "test goal " + chr(name_appendix)) # by default sort by name ASC name_appendix = name_appendix + 1 self.assertTrue(is_public) self.assertFalse(is_private) ## Only shows public goals for other users self.logout() self.login_other_user() res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 name_appendix = ord('a') is_public = False ## Test to make sure at least one is public is_private = False # none should be private for goal in data['goals']: if (goal['public']): is_public = True else: is_private = True self.assertTrue(goal['active']) # by default they're all active self.assertEqual(goal['name'], "test goal " + chr(name_appendix)) # by default sort by name ASC name_appendix = name_appendix + 1 self.assertTrue(is_public) self.assertFalse(is_private) public_goals = db.session.query(Goal).all() for goal in public_goals: goal.update({"public": False}) res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 0) # No public goals ## Count works public_goals = db.session.query(Goal).all() for goal in public_goals: goal.update({"public": True}) res = self.test_client.get("/goals/users/" + user_id + "/?count=3") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 3) # default count is 20 name_appendix = chr(ord('a') - 1) for goal in data['goals']: self.assertTrue(goal['active']) # by default they're all active new_appendix = goal['name'].replace("test goal ", "") self.assertTrue(ord(new_appendix) > ord(name_appendix)) name_appendix = new_appendix ## Sort rejects invalid inputs res = self.test_client.get("/goals/users/" + user_id + "/?sort=banana") setup.assertBadData(self, res, "sort can only be one of") ## Sort works ## Sort works -- and it should always give active first, then inactive active_goals = db.session.query(Goal).order_by(func.rand()).limit(15) for goal in active_goals: goal.update({"active": False}) res = self.test_client.get("/goals/users/" + user_id + "/?sort=created") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 is_active = False is_inactive = False test_created = str(datetime.datetime(1970, 1, 1, 0, 0, 0)) for goal in data['goals']: if (goal['active']): is_active = True if (not goal['active']): if (not is_inactive): test_created = str(datetime.datetime(1970, 1, 1, 0, 0, 0)) # reset the sort on the first inactive goal is_inactive = True self.assertTrue(goal['created'] > test_created) test_created = goal['created'] self.assertTrue(is_active) self.assertTrue(is_inactive) ## Sort order rejects invalid inputs res = self.test_client.get("/goals/users/" + user_id + "/?sort_order=banana") setup.assertBadData(self, res, "sort_order must be either") ## Sort_order works res = self.test_client.get("/goals/users/" + user_id + "/?sort=created&sort_order=desc") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 is_active = False is_inactive = False test_created = str(datetime.datetime(2100, 1, 1, 0, 0, 0)) for goal in data['goals']: if (goal['active']): is_active = True if (not goal['active']): if (not is_inactive): test_created = str(datetime.datetime(2100, 1, 1, 0, 0, 0)) # reset the sort on the first inactive goal is_inactive = True self.assertTrue(goal['created'] < test_created) test_created = goal['created'] self.assertTrue(is_active) self.assertTrue(is_inactive) ## Offset works min_name = db.session.query(Goal).filter_by(active=True).order_by(Goal.name).first().name res = self.test_client.get("/goals/users/" + user_id + "/?offset=1") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 self.assertTrue(data['goals'][0]['name'] > min_name) ## Count, sort, sort order, and offset all work together max_created = db.session.query(Goal).filter_by(active=True).order_by(Goal.created.desc()).first().created res = self.test_client.get("/goals/users/" + user_id + "/?offset=1&count=1&sort=created&sort_order=desc") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 1) self.assertTrue(data['goals'][0]['created'] < str(max_created))
def test_update(self): ## Requires login res = self.test_client.post("/goals/update/", data={'id': 0}) setup.assertRequiresLogin(self, res) ## Validates form self.login() res = self.test_client.post("/goals/update/", data={'favorite_muppet': 'kermit'}) setup.assertInvalid(self, res, 'id') ## 404's res = self.test_client.post("/goals/update/", data={'id': 0, 'name': 'test goal 2.0'}) setup.assert404(self, res) ## Actually works goal = self.create_test_goal() data = {'id': goal['id']} data['name'] = "Test Goal 2.0" data['prompt'] = "Guess how many eggs I had for breakfast today!" data['frequency'] = "monthly" data['target'] = 100 data['input_type'] = "binary" data['active'] = False data['public'] = True data['check_in_frequency'] = "daily" res = self.test_client.post("/goals/update/", data=data) setup.assertOk(self, res, 200) updated_goal = Goal.pull_by_id(goal['id']) for key, val in data.iteritems(): if (key == 'frequency' or key == 'check_in_frequency'): self.assertEqual(Frequency.get_name_by_id(getattr(updated_goal, key)), val) else: self.assertEqual(getattr(updated_goal, key), val) ## If any part is invalid, no part should go through bad_data = {'id': goal['id']} bad_data['name'] = "Test Goal 3.0" bad_data['prompt'] = "How many jars of sand did you collect?" bad_data['frequency'] = "daily" bad_data['target'] = 1000 bad_data['input_type'] = "numeric" bad_data['active'] = True bad_data['public'] = "banana" bad_data['check_in_frequency'] = "daily" res = self.test_client.post("/goals/update/", data=bad_data) setup.assertBadData(self, res, "Public must be a boolean") updated_goal = Goal.pull_by_id(goal['id']) for key, val in data.iteritems(): if (key == 'frequency' or key == 'check_in_frequency'): self.assertEqual(Frequency.get_name_by_id(getattr(updated_goal, key)), val) else: self.assertEqual(getattr(updated_goal, key), val) ## Can't update someone else's goal self.logout() self.login_other_user() res = self.test_client.post("/goals/update/", data=bad_data) ## using bad_data here ensures we don't update setup.assertInvalidCredentials(self, res)
def test_check_in(self): tc = self.test_client # Requires Login: res = tc.post("/goals/1/check-ins/", data={"value": 1}) setup.assertRequiresLogin(self, res) ## Requires "value" self.login() res = tc.post("/goals/1/check-ins/", data={"not-value": 1}) setup.assertInvalid(self, res, "value") ## Must be a goal that exists res = tc.post("/goals/0/check-ins/", data={"value": 1}) setup.assert404(self, res) ## User must own the goal in question numeric_goal = self.create_test_numeric_goal() numeric_goal_id = str(numeric_goal.get_id()) ## You have to do this before you log out, for some reason? binary_goal = self.create_test_binary_goal() binary_goal_id = str(binary_goal.get_id()) self.logout() self.login_other_user() res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 1}) setup.assertInvalidCredentials(self, res) ## Check-in must conform (true / false vs. numeric) self.logout() self.login() res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": "true"}) setup.assertBadData(self, res, "Value must be numeric") res = tc.post("/goals/" + binary_goal_id + "/check-ins/", data={"value": 10}) setup.assertBadData(self, res, "Value must be a boolean") ## Check-in is returned with 201 if no timeframe is given, returning current timeframe (both numeric & binary) res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 1}) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 1) self.assertEqual(data['timeframe'], Timeframe.get_current_timeframe('daily').to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) res = tc.post("/goals/" + binary_goal_id + "/check-ins/", data={"value": True}) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), binary_goal_id) self.assertEqual(data['value'], 1) self.assertEqual(data['timeframe'], Timeframe.get_current_timeframe('daily').to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) ## An updated check-in is returned with 200 if no timeframe is given, returning current timeframe res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 3}) setup.assertOk(self, res, 200) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 3) self.assertEqual(data['timeframe'], Timeframe.get_current_timeframe('daily').to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) ## Check-in is returned with 201 if timeframe ID is given, returning correct timeframe tf = Timeframe.get_timeframe("daily", datetime.datetime(2016, 1, 1)) res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 1, "timeframe": tf.get_id()}) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 1) self.assertEqual(data['timeframe'], tf.to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) ## Updated check-in is returned with 200 if Timeframe ID is given, returning correct timeframe res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 3, "timeframe": tf.get_id()}) setup.assertOk(self, res, 200) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 3) self.assertEqual(data['timeframe'], tf.to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data)
def login_other_user(self): return setup.assertOk(self, setup.login_other_user(), 201)
def create_test_goal(self): res = self.test_client.post("/goals/create/", data=self.new_goal) setup.assertOk(self, res, 201) return json.loads(res.data)
def test_update(self): ## Requires login res = self.test_client.post("/goals/update/", data={'id': 0}) setup.assertRequiresLogin(self, res) ## Validates form self.login() res = self.test_client.post("/goals/update/", data={'favorite_muppet': 'kermit'}) setup.assertInvalid(self, res, 'id') ## 404's res = self.test_client.post("/goals/update/", data={ 'id': 0, 'name': 'test goal 2.0' }) setup.assert404(self, res) ## Actually works goal = self.create_test_goal() data = {'id': goal['id']} data['name'] = "Test Goal 2.0" data['prompt'] = "Guess how many eggs I had for breakfast today!" data['frequency'] = "monthly" data['target'] = 100 data['input_type'] = "binary" data['active'] = False data['public'] = True data['check_in_frequency'] = "daily" res = self.test_client.post("/goals/update/", data=data) setup.assertOk(self, res, 200) updated_goal = Goal.pull_by_id(goal['id']) for key, val in data.iteritems(): if (key == 'frequency' or key == 'check_in_frequency'): self.assertEqual( Frequency.get_name_by_id(getattr(updated_goal, key)), val) else: self.assertEqual(getattr(updated_goal, key), val) ## If any part is invalid, no part should go through bad_data = {'id': goal['id']} bad_data['name'] = "Test Goal 3.0" bad_data['prompt'] = "How many jars of sand did you collect?" bad_data['frequency'] = "daily" bad_data['target'] = 1000 bad_data['input_type'] = "numeric" bad_data['active'] = True bad_data['public'] = "banana" bad_data['check_in_frequency'] = "daily" res = self.test_client.post("/goals/update/", data=bad_data) setup.assertBadData(self, res, "Public must be a boolean") updated_goal = Goal.pull_by_id(goal['id']) for key, val in data.iteritems(): if (key == 'frequency' or key == 'check_in_frequency'): self.assertEqual( Frequency.get_name_by_id(getattr(updated_goal, key)), val) else: self.assertEqual(getattr(updated_goal, key), val) ## Can't update someone else's goal self.logout() self.login_other_user() res = self.test_client.post( "/goals/update/", data=bad_data) ## using bad_data here ensures we don't update setup.assertInvalidCredentials(self, res)
def test_get_by_time(self): tc = self.test_client ## Login required setup.assertRequiresLogin(self, tc.get("/goals/0/check-ins/")) ## Goal must exist self.login() setup.assert404(self, tc.get("/goals/0/check-ins/")) ## User is the goal's owner goal = self.create_test_numeric_goal() goal_id = str(goal.get_id()) self.logout() self.login_other_user() setup.assertInvalidCredentials( self, tc.get("/goals/" + goal_id + "/check-ins/")) ## Start and end are present self.logout() self.login() setup.assertBadData(self, tc.get("/goals/" + goal_id + "/check-ins/"), "start and end") setup.assertBadData( self, tc.get("/goals/" + goal_id + "/check-ins/?start=banana"), "start and end") setup.assertBadData( self, tc.get("/goals/" + goal_id + "/check-ins/?end=banana"), "start and end") ## Start and end in format YYYY-MM-DD HH:mm:ss res = tc.get("/goals/" + goal_id + "/check-ins/?start=2016-01-01 10:00:00&end=banana") setup.assertBadData(self, res, "'banana' does not match format") res = tc.get("/goals/" + goal_id + "/check-ins/?start=strawberry&end=2016-01-01 10:00:00") setup.assertBadData(self, res, "'strawberry' does not match format") ## Returns empty for no check-ins res = tc.get( "/goals/" + goal_id + "/check-ins/?start=2016-01-01 00:00:00&end=2016-01-08 00:00:00") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("check-ins", data) self.assertEqual(len(data['check-ins']), 0) ## Correctly returns multiple check-ins ci = CheckIn( goal, Timeframe(goal.check_in_frequency_name, datetime.datetime(2015, 12, 31)), 0) ci.persist() for x in range( 0, 8 ): #one preceding and one postceding so we can make sure this limits the results tf = ci.timeframe_obj new_tf = Timeframe(tf.frequency_name, tf.start + datetime.timedelta(1)) ci = CheckIn(ci.goal_obj, new_tf, x) ci.persist() res = tc.get( "/goals/" + goal_id + "/check-ins/?start=2016-01-01 00:00:00&end=2016-01-08 00:00:00") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("check-ins", data) self.assertEqual(len(data['check-ins']), 7) for index, check_in in enumerate(data['check-ins']): self.assertEqual(index, check_in['value'])
def test_index(self): ## Requires login res = self.test_client.get("/goals/users/0/") setup.assertRequiresLogin(self, res) ## 404s on bum user self.login() res = self.test_client.get("/goals/users/0/") setup.assert404(self, res) # Empty if user has no goals user_id = str( json.loads(self.test_client.get("/users/me/").data)['id']) res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 0) ## Shows only public goals even for current user setup.create_test_goals() res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 0) # No public goals public_goals = db.session.query(Goal).all() for goal in public_goals: goal.update({"public": True}) res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 name_appendix = ord('a') is_public = False ## Test to make sure at least one is public is_private = False # none should be private for goal in data['goals']: if (goal['public']): is_public = True else: is_private = True self.assertTrue(goal['active']) # by default they're all active self.assertEqual(goal['name'], "test goal " + chr(name_appendix)) # by default sort by name ASC name_appendix = name_appendix + 1 self.assertTrue(is_public) self.assertFalse(is_private) ## Only shows public goals for other users self.logout() self.login_other_user() res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 name_appendix = ord('a') is_public = False ## Test to make sure at least one is public is_private = False # none should be private for goal in data['goals']: if (goal['public']): is_public = True else: is_private = True self.assertTrue(goal['active']) # by default they're all active self.assertEqual(goal['name'], "test goal " + chr(name_appendix)) # by default sort by name ASC name_appendix = name_appendix + 1 self.assertTrue(is_public) self.assertFalse(is_private) public_goals = db.session.query(Goal).all() for goal in public_goals: goal.update({"public": False}) res = self.test_client.get("/goals/users/" + user_id + "/") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 0) # No public goals ## Count works public_goals = db.session.query(Goal).all() for goal in public_goals: goal.update({"public": True}) res = self.test_client.get("/goals/users/" + user_id + "/?count=3") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 3) # default count is 20 name_appendix = chr(ord('a') - 1) for goal in data['goals']: self.assertTrue(goal['active']) # by default they're all active new_appendix = goal['name'].replace("test goal ", "") self.assertTrue(ord(new_appendix) > ord(name_appendix)) name_appendix = new_appendix ## Sort rejects invalid inputs res = self.test_client.get("/goals/users/" + user_id + "/?sort=banana") setup.assertBadData(self, res, "sort can only be one of") ## Sort works ## Sort works -- and it should always give active first, then inactive active_goals = db.session.query(Goal).order_by(func.rand()).limit(15) for goal in active_goals: goal.update({"active": False}) res = self.test_client.get("/goals/users/" + user_id + "/?sort=created") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 is_active = False is_inactive = False test_created = str(datetime.datetime(1970, 1, 1, 0, 0, 0)) for goal in data['goals']: if (goal['active']): is_active = True if (not goal['active']): if (not is_inactive): test_created = str(datetime.datetime( 1970, 1, 1, 0, 0, 0)) # reset the sort on the first inactive goal is_inactive = True self.assertTrue(goal['created'] > test_created) test_created = goal['created'] self.assertTrue(is_active) self.assertTrue(is_inactive) ## Sort order rejects invalid inputs res = self.test_client.get("/goals/users/" + user_id + "/?sort_order=banana") setup.assertBadData(self, res, "sort_order must be either") ## Sort_order works res = self.test_client.get("/goals/users/" + user_id + "/?sort=created&sort_order=desc") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 is_active = False is_inactive = False test_created = str(datetime.datetime(2100, 1, 1, 0, 0, 0)) for goal in data['goals']: if (goal['active']): is_active = True if (not goal['active']): if (not is_inactive): test_created = str(datetime.datetime( 2100, 1, 1, 0, 0, 0)) # reset the sort on the first inactive goal is_inactive = True self.assertTrue(goal['created'] < test_created) test_created = goal['created'] self.assertTrue(is_active) self.assertTrue(is_inactive) ## Offset works min_name = db.session.query(Goal).filter_by(active=True).order_by( Goal.name).first().name res = self.test_client.get("/goals/users/" + user_id + "/?offset=1") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 20) # default count is 20 self.assertTrue(data['goals'][0]['name'] > min_name) ## Count, sort, sort order, and offset all work together max_created = db.session.query(Goal).filter_by(active=True).order_by( Goal.created.desc()).first().created res = self.test_client.get( "/goals/users/" + user_id + "/?offset=1&count=1&sort=created&sort_order=desc") setup.assertOk(self, res) data = json.loads(res.data) self.assertIn("goals", data) self.assertEqual(len(data['goals']), 1) self.assertTrue(data['goals'][0]['created'] < str(max_created))
def test_check_in(self): tc = self.test_client # Requires Login: res = tc.post("/goals/1/check-ins/", data={"value": 1}) setup.assertRequiresLogin(self, res) ## Requires "value" self.login() res = tc.post("/goals/1/check-ins/", data={"not-value": 1}) setup.assertInvalid(self, res, "value") ## Must be a goal that exists res = tc.post("/goals/0/check-ins/", data={"value": 1}) setup.assert404(self, res) ## User must own the goal in question numeric_goal = self.create_test_numeric_goal() numeric_goal_id = str(numeric_goal.get_id( )) ## You have to do this before you log out, for some reason? binary_goal = self.create_test_binary_goal() binary_goal_id = str(binary_goal.get_id()) self.logout() self.login_other_user() res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 1}) setup.assertInvalidCredentials(self, res) ## Check-in must conform (true / false vs. numeric) self.logout() self.login() res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": "true"}) setup.assertBadData(self, res, "Value must be numeric") res = tc.post("/goals/" + binary_goal_id + "/check-ins/", data={"value": 10}) setup.assertBadData(self, res, "Value must be a boolean") ## Check-in is returned with 201 if no timeframe is given, returning current timeframe (both numeric & binary) res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 1}) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 1) self.assertEqual(data['timeframe'], Timeframe.get_current_timeframe('daily').to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) res = tc.post("/goals/" + binary_goal_id + "/check-ins/", data={"value": True}) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), binary_goal_id) self.assertEqual(data['value'], 1) self.assertEqual(data['timeframe'], Timeframe.get_current_timeframe('daily').to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) ## An updated check-in is returned with 200 if no timeframe is given, returning current timeframe res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={"value": 3}) setup.assertOk(self, res, 200) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 3) self.assertEqual(data['timeframe'], Timeframe.get_current_timeframe('daily').to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) ## Check-in is returned with 201 if timeframe ID is given, returning correct timeframe tf = Timeframe.get_timeframe("daily", datetime.datetime(2016, 1, 1)) res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={ "value": 1, "timeframe": tf.get_id() }) setup.assertOk(self, res, 201) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 1) self.assertEqual(data['timeframe'], tf.to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data) ## Updated check-in is returned with 200 if Timeframe ID is given, returning correct timeframe res = tc.post("/goals/" + numeric_goal_id + "/check-ins/", data={ "value": 3, "timeframe": tf.get_id() }) setup.assertOk(self, res, 200) data = json.loads(res.data) self.assertIn("id", data) self.assertEqual(str(data['goal']), numeric_goal_id) self.assertEqual(data['value'], 3) self.assertEqual(data['timeframe'], tf.to_dict()) self.assertEqual(CheckIn.pull_by_id(data['id']).to_dict(), data)