Beispiel #1
0
def test_remove():
    """Try adding a bunch of observations, and delete a couple items"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    time = datetime.fromtimestamp(0)
    for l in string.ascii_lowercase:
        time += timedelta(minutes=random.randint(1, 10))
        app.post('/add/', {'suspect': l, 'location': l.upper(), 'time': time})

    # We should have all 26
    assert len(glob("observations/*.json")) == 26

    for obs_name in glob("observations/*.json"):
        obs_id = os.path.basename(obs_name).rstrip('.json')

        # The file should be in there
        assert obs_name in glob("observations/*.json")

        # Get the form (to make sure it doesn't change anything on disk)
        app.get('/remove/{}/'.format(obs_id))

        # The file should still be in there
        assert obs_name in glob("observations/*.json")

        # Try to delete it
        app.post('/remove/{}/'.format(obs_id))

        # The file should be gone
        assert obs_name not in glob("observations/*.json")

    # Ain't nothin' left, I'll tell ya what.
    assert len(glob("observations/*.json")) == 0
Beispiel #2
0
def test_login_form_alerts():
    """Make sure login forms are validated"""
    app = HelperApp(server.observation_app)

    # Use bad field names
    response = app.post('/login/', {'usernam': 'carmon', 'passwor': 'frog'})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/login/"

    # Check for alerts
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 2
    assert alerts == [
        {'kind': 'danger', 'message': 'Missing username field!'},
        {'kind': 'danger', 'message': 'Missing password field!'}
    ]

    # Clear EVERYTHING (including alerts)
    app.reset()

    # Use blank field names
    response = app.post('/login/', {'username': '', 'password': ''})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/login/"

    # Check for alerts
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 2
    assert alerts == [
        {'kind': 'danger', 'message': 'username field cannot be blank!'},
        {'kind': 'danger', 'message': 'password field cannot be blank!'}
    ]
Beispiel #3
0
def test_message_structure():
    """Make sure that our saved messages contain the types we want."""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a bunch of messages
    for l in string.ascii_lowercase:
        app.get('/compose/')
        app.post('/compose/', {'to': 'james', 'subject': l, 'body': l.upper()})

    all_messages = message.load_all_messages()
    sent_messages = message.load_sent_messages('jessie')
    received_messages = message.load_sent_messages('james')

    # Check that we're loading messages correctly
    for messages in (all_messages, sent_messages, received_messages):
        for m in messages:
            # Check that our keys match up
            assert set(m) == {'id', 'from', 'to', 'subject', 'body', 'time'}

            # Check that load_all_messages loads the correct types
            assert isinstance(m['to'], str)
            assert isinstance(m['from'], str)
            assert isinstance(m['subject'], str)
            assert isinstance(m['body'], str)
            assert isinstance(m['time'], datetime)
Beispiel #4
0
def test_download():
    """Try adding a bunch of observations, and clear them out"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    time = datetime.fromtimestamp(0)
    for l in string.ascii_lowercase:
        time += timedelta(minutes=random.randint(1, 10))
        app.post('/add/', {'suspect': l, 'location': l.upper(), 'time': time})

    # We should have all 26
    assert len(glob("observations/*.json")) == 26

    # This shouldn't change the files
    response = app.get('/download/')

    # We should have all 26 as rows in the CSV file
    assert len(response.text.splitlines()) == 26

    # We know they'll be in reversed alphabetical order, since we
    # increased the time as we added them and they're sorted most
    # recent to least recent.
    reader = csv.reader(io.StringIO(response.text))
    for letter, row in zip(reversed(string.ascii_lowercase), reader):
        suspect, location, time = row
        assert suspect == letter
        assert location == letter.upper()
Beispiel #5
0
def test_view_authorization():
    """Make sure that we can only view messages to/from us."""
    app = HelperApp(server.message_app)

    # Send a message from Jessie to James
    app.post('/login/', {'username': '******', 'password': '******'})
    app.get('/compose/')
    app.post('/compose/', {'to': 'james', 'subject': 's', 'body': 'S'})

    # Find the message
    msg, = message.load_sent_messages('jessie')

    # Make sure Jessie can see it
    response = app.get('/view/{}/'.format(msg['id']))
    assert response.status == "200 OK"

    # Make sure James can see it
    app.get('/logout/')
    app.post('/login/', {'username': '******', 'password': '******'})
    response = app.get('/view/{}/'.format(msg['id']))
    assert response.status == "200 OK"

    # Make sure Cassidy can't
    app.get('/logout/')
    app.post('/login/', {'username': '******', 'password': '******'})
    response = app.get('/view/{}/'.format(msg['id']))
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/"
Beispiel #6
0
def test_delete():
    """Try adding a bunch of messages, and delete a couple items"""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    for l in string.ascii_lowercase:
        app.post('/compose/', {'to': 'james', 'subject': l, 'body': l.upper()})

    # We should have all 26
    assert len(glob("messages/*.json")) == 26

    for msg_name in glob("messages/*.json"):
        msg_id = os.path.basename(msg_name).rstrip('.json')

        # The file should be in there
        assert msg_name in glob("messages/*.json")

        # Get the form (to make sure it doesn't change anything on disk)
        app.get('/delete/{}/'.format(msg_id))

        # The file should still be in there
        assert msg_name in glob("messages/*.json")

        # Try to delete it
        app.post('/delete/{}/'.format(msg_id))

        # The file should be gone
        assert msg_name not in glob("messages/*.json")

    # Ain't nothin' left, I'll tell ya what.
    assert len(glob("messages/*.json")) == 0
Beispiel #7
0
def test_logout():
    """Make sure logout works as we expect"""
    app = HelperApp(server.observation_app)
    response = app.post('/login/', {'username': '******', 'password': '******'})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/"
    assert app.cookies['logged_in_as'] == "carmen"

    response = app.get('/logout/')
    assert response.status == "200 OK"
    assert app.cookies['logged_in_as'] == ""
Beispiel #8
0
def assert_redirect_to_login(path):
    """A helper function to test that we're redirected if we're not
    logged in.

    """
    app = HelperApp(server.observation_app)

    # Assert that we get redirected
    response = app.get(path)
    assert response.status == "302 Found"

    # Make sure the redirect is going to the right place
    assert urlsplit(response.location).path == "/login/"
Beispiel #9
0
def assert_not_redirect_to_login(path):
    """A helper function to test that we're not redirected if we're
    logged in.

    """
    app = HelperApp(server.observation_app)

    # Login as Carmen
    app.post('/login/', {'username': '******', 'password': '******'})

    # Assert that we're not redirected
    response = app.get(path)
    assert response.status == "200 OK"
Beispiel #10
0
def test_load_observations_order():
    """Make sure that load_observations maintains order for us."""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a bunch of observations
    time = datetime.fromtimestamp(0)
    for l in string.ascii_lowercase:
        time += timedelta(minutes=random.randint(1, 10))
        app.get('/add/')
        app.post('/add/', {'suspect': l, 'location': l.upper(), 'time': time})

    all_obs = observation.load_observations()
    for prev, current in zip(all_obs, all_obs[1:]):
        assert prev['time'] > current['time']
Beispiel #11
0
def test_compose_success_alerts():
    """Try adding an message and check for success messages."""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Clear alerts
    app.get('/')

    # Add a message
    app.post('/compose/', {'to': 'james', 'subject': "frog", 'body': "FROG!"})

    # Unpack the alerts from the session cookie, and assert that we
    # see the right message
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1, "Expected exactly one alert message"
    assert alerts == [{'kind': 'success', 'message': 'Message sent!'}]
Beispiel #12
0
def test_shred_success_alert():
    """Try shreding messages, ensuring there's a success message"""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a an message
    app.post('/compose/', {'to': 'james', 'subject': 's', 'body': 'b'})
    app.get('/')  # Clears alerts

    # Remove something bogus
    app.post('/shred/')

    # Make sure we warn the user about it
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1
    assert alerts == [{'kind': 'success', 'message': 'Shreded all messages.'}]
Beispiel #13
0
def test_add_bad_time_alert():
    """Check that we warn for bad time formatting"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Clear alerts
    app.get('/')

    # Bad time field
    app.post('/add/', {'suspect': "A", 'location': "B", 'time': "nope"})

    # Make sure we warn
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1
    assert alerts == [{'kind': 'danger',
                       'message': "Bad time format: time data 'nope' does "
                                  "not match format '%Y-%m-%d %H:%M:%S'"}]
Beispiel #14
0
def test_add_success_alerts():
    """Try adding an observation and check for success messages."""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Clear alerts
    app.get('/')

    # Add an observation
    time = datetime.fromtimestamp(0)
    app.post('/add/', {'suspect': "Frog", 'location': "Place", 'time': time})

    # Unpack the alerts from the session cookie, and assert that we
    # see the right message
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1, "Expected exactly one alert message"
    assert alerts == [{'kind': 'success',
                       'message': 'New observation added!'}]
Beispiel #15
0
def test_clear_success_alert():
    """Try clearing observations, ensuring there's a success message"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a an observation
    time = datetime.fromtimestamp(0)
    app.post('/add/', {'suspect': 'a', 'location': 'b', 'time': time})
    app.get('/')        # Clears alerts

    # Remove something bogus
    app.post('/clear/')

    # Make sure we warn the user about it
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1
    assert alerts == [{'kind': 'success',
                       'message': 'Cleared all observations.'}]
Beispiel #16
0
def test_compose_form_validation():
    """Check that we warn for bad forms"""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Clear alerts
    app.get('/')

    # Missing fields
    app.post('/compose/', {'subjec': 'A', 'two': 'B', 'bodee': 'nope'})

    # Make sure we warn
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 3
    assert all(a['kind'] == 'danger' for a in alerts)
    assert set(a['message'] for a in alerts) == {
        "Missing subject field!", "Missing to field!", "Missing body field!"
    }
Beispiel #17
0
def test_add_missing_fields_alerts():
    """Check that we warn for missing fields"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Clear alerts
    app.get('/')

    # Blank fields
    app.post('/add/', {'suspect': "", 'location': "", 'time': ""})

    # Make sure we warn
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 3
    assert alerts == [
        {'kind': 'danger', 'message': 'suspect field cannot be blank!'},
        {'kind': 'danger', 'message': 'location field cannot be blank!'},
        {'kind': 'danger', 'message': 'time field cannot be blank!'},
    ]
Beispiel #18
0
def test_compose_missing_fields_alerts():
    """Check that we warn for missing fields"""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Clear alerts
    app.get('/')

    # Blank fields
    app.post('/compose/', {'to': '', 'subject': '', 'body': ''})

    # Make sure we warn
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 3
    assert all(a['kind'] == 'danger' for a in alerts)
    assert set(a['message'] for a in alerts) == {
        'to field cannot be blank!', 'subject field cannot be blank!',
        'body field cannot be blank!'
    }
Beispiel #19
0
def test_add_form_validation():
    """Check that we warn for bad forms"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Clear alerts
    app.get('/')

    # Missing fields
    app.post('/add/', {'suspec': "A", 'locatio': "B", 'tim': "nope"})

    # Make sure we warn
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 3
    assert alerts == [
        {'kind': 'danger', 'message': "Missing suspect field!"},
        {'kind': 'danger', 'message': "Missing location field!"},
        {'kind': 'danger', 'message': "Missing time field!"}
    ]
Beispiel #20
0
def test_sent_messages():
    """Make sure that we're filtering received messages properly."""
    app = HelperApp(server.message_app)

    # Get a list of people to send messages to (everyone who's not Jessie)
    with open("passwords.json") as f:
        passwords = json.load(f)
        people = set(passwords.keys())

    # Add a bunch of messages (26)
    for l in string.ascii_lowercase:
        sender = random.choice(list(people))
        receiver = random.choice(list(people - set(sender)))
        app.post('/login/', {
            'username': sender,
            'password': passwords[sender]
        })

        app.get('/compose/')
        app.post('/compose/', {
            'to': receiver,
            'subject': l,
            'body': l.upper()
        })

    sent = {}
    for person in people:
        messages = message.load_sent_messages(person)
        sent[person] = messages

        # It's extremely improbable that all of the messages would go to
        # the same person.
        assert len(messages) < 26

        for m in messages:
            assert m['from'] == person

    # We should have seen 26 total messages
    assert sum(len(l) for l in sent.values()) == 26

    # We should have 26 unique messages
    assert len(set(x['id'] for l in sent.values() for x in l)) == 26
Beispiel #21
0
def test_remove_success_alert():
    """Try removing an observation, ensuring there's a success message"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a an observation
    time = datetime.fromtimestamp(0)
    app.post('/add/', {'suspect': 'a', 'location': 'b', 'time': time})
    app.get('/')        # Clears alerts

    # Remove something real
    obs_file, = glob("observations/*.json")
    obs_id = os.path.basename(obs_file).rstrip('.json')
    app.post('/remove/{}/'.format(obs_id))

    # Make sure we display a success message
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1
    assert alerts == [{'kind': 'success',
                       'message': 'Removed {}.'.format(obs_id)}]
Beispiel #22
0
def test_remove_bogus_alert():
    """Try removing a bogus observation, ensuring there's a warning"""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a an observation
    time = datetime.fromtimestamp(0)
    app.post('/add/', {'suspect': 'a', 'location': 'b', 'time': time})
    app.get('/')        # Clears alerts

    # Remove something bogus
    # Pick some arbitrary UUID. Collision is improbable.
    bogus_uuid = "b58cba44-da39-11e5-9342-56f85ff10656"
    app.post('/remove/{}/'.format(bogus_uuid))

    # Make sure we warn the user about it
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1
    assert alerts == [{'kind': 'danger',
                       'message': 'No such observation {}'.format(bogus_uuid)}]
Beispiel #23
0
def test_delete_success_alert():
    """Try removing an message, ensuring there's a success message"""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a an message
    app.post('/compose/', {'to': 'james', 'subject': 's', 'body': 'S'})
    app.get('/')  # Clears alerts

    # Delete something real
    msg_file, = glob("messages/*.json")
    msg_id = os.path.basename(msg_file).rstrip('.json')
    app.post('/delete/{}/'.format(msg_id))

    # Make sure we display a success message
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1
    assert alerts == [{
        'kind': 'success',
        'message': 'Deleted {}.'.format(msg_id)
    }]
Beispiel #24
0
def test_delete_bogus_alert():
    """Try removing a bogus message, ensuring there's a warning"""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a message
    app.post('/compose/', {'to': 'james', 'subject': 's', 'body': 'b'})
    app.get('/')  # Clears alerts

    # Remove something bogus
    # Pick some arbitrary UUID. Collision is improbable.
    bogus_uuid = "b58cba44-da39-11e5-9342-56f85ff10656"
    app.post('/delete/{}/'.format(bogus_uuid))

    # Make sure we warn the user about it
    alerts = unpack_alerts(app.cookies)
    assert len(alerts) == 1
    assert alerts == [{
        'kind': 'danger',
        'message': 'No such message {}'.format(bogus_uuid)
    }]
Beispiel #25
0
def test_add_files():
    """Try adding a bunch of observations, ensuring that files are created
    on disk.

    """
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    time = datetime.fromtimestamp(0)
    for l in string.ascii_lowercase:
        time += timedelta(minutes=random.randint(1, 10))
        app.get('/add/')
        app.post('/add/', {'suspect': l, 'location': l.upper(), 'time': time})

    obs_filenames = glob("observations/*.json")
    assert len(obs_filenames) == 26

    letters = set()
    for obs_name in obs_filenames:
        with open(obs_name) as obs_file:
            obs_data = json.load(obs_file)

        # Assert that the set of keys is what we want
        assert set(obs_data) == {"reporter", "suspect", "location", "time"}

        # Since we're logged in as Carmen
        assert obs_data['reporter'] == 'carmen'

        # Check that we saved the suspect and location correctly
        # (location is the uppercase version of suspect)
        assert ord(obs_data['suspect']) == ord(obs_data['location']) + 32

        # Remember all the letters we've seen so far
        letters.add(obs_data['suspect'])

        # Make sure we can load the time correctly -- shouldn't throw
        # an exception
        datetime.strptime(obs_data['time'], "%Y-%m-%d %H:%M:%S")

    assert letters == set(string.ascii_lowercase)
Beispiel #26
0
def test_load_observations_type():
    """Make sure that load_observations returns the types we want."""
    app = HelperApp(server.observation_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a bunch of observations
    time = datetime.fromtimestamp(0)
    for l in string.ascii_lowercase:
        time += timedelta(minutes=random.randint(1, 10))
        app.get('/add/')
        app.post('/add/', {'suspect': l, 'location': l.upper(), 'time': time})

    for o in observation.load_observations():
        # Check that our keys match up
        assert set(o) == {'id', 'reporter', 'suspect', 'location', 'time'}

        # Check all the types
        assert isinstance(o['id'], str)
        assert isinstance(o['reporter'], str)
        assert isinstance(o['suspect'], str)
        assert isinstance(o['location'], str)
        assert isinstance(o['time'], datetime)
Beispiel #27
0
def test_shred():
    """Try adding a bunch of messages, and clear them out"""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    for l in string.ascii_lowercase:
        app.post('/compose/', {'to': 'james', 'subject': l, 'body': l.upper()})

    # We should have all 26
    assert len(glob("messages/*.json")) == 26

    # This shouldn't change the files
    app.get('/shred/')

    # We should still have all 26
    assert len(glob("messages/*.json")) == 26

    # Delete all the message files
    app.post('/shred/')

    # OK, now they're gone.
    assert len(glob("messages/*.json")) == 0
Beispiel #28
0
def test_order_of_loaded_messages():
    """Make sure that load_messages maintains order for us."""
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    # Add a bunch of messages
    for i, l in enumerate("abcd"):
        # Sleep a second so that our messages have different timestamps
        if i != 0:
            time.sleep(1)

        app.get('/compose/')
        app.post('/compose/', {'to': 'james', 'subject': l, 'body': l.upper()})

    all_messages = message.load_all_messages()
    sent_messages = message.load_sent_messages('jessie')
    received_messages = message.load_sent_messages('james')

    # Check that we're loading messages correctly
    for messages in (all_messages, sent_messages, received_messages):
        for prev, current in zip(messages, messages[1:]):
            assert prev['time'] > current['time']
Beispiel #29
0
def test_compose_files():
    """Try adding a bunch of messages, ensuring that files are created
    on disk.

    """
    app = HelperApp(server.message_app)
    app.post('/login/', {'username': '******', 'password': '******'})

    for l in string.ascii_lowercase:
        app.get('/compose/')
        app.post('/compose/', {'to': 'james', 'subject': l, 'body': l.upper()})

    msg_filenames = glob("messages/*.json")
    assert len(msg_filenames) == 26

    letters = set()
    for msg_name in msg_filenames:
        with open(msg_name) as msg_file:
            msg_data = json.load(msg_file)

        # Assert that the set of keys is what we want
        assert set(msg_data) == {'body', 'subject', 'to', 'from', 'time'}

        # Since we're logged in as Jessie
        assert msg_data['from'] == 'jessie'

        # Check that we saved the subject and body correctly
        # (body is the uppercase version of subject)
        assert ord(msg_data['subject']) == ord(msg_data['body']) + 32

        # Remember all the letters we've seen so far
        letters.add(msg_data['subject'])

        # Make sure we can load the time correctly -- shouldn't throw
        # an exception
        datetime.strptime(msg_data['time'], "%Y-%m-%d %H:%M:%S")

    assert letters == set(string.ascii_lowercase)
Beispiel #30
0
def test_login():
    """Make sure login works as we expect"""
    app = HelperApp(server.observation_app)

    # The page loads up
    response = app.get('/login/')
    assert response.status == "200 OK"

    # Doesn't work with a bad username
    response = app.post('/login/', {'username': '******', 'password': '******'})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/login/"
    assert app.cookies.get('logged_in_as') is None

    # Doesn't work with a bad password
    response = app.post('/login/', {'username': '******', 'password': '******'})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/login/"
    assert app.cookies.get('logged_in_as') is None

    # Doesn't work with arbitrary password capitalization
    response = app.post('/login/', {'username': '******', 'password': '******'})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/login/"
    assert app.cookies.get('logged_in_as') is None

    # Works with a good password
    response = app.post('/login/', {'username': '******', 'password': '******'})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/"
    assert app.cookies['logged_in_as'] == "carmen"

    # Works with various username capitalization
    response = app.post('/login/', {'username': '******', 'password': '******'})
    assert response.status == "302 Found"
    assert urlsplit(response.location).path == "/"
    assert app.cookies['logged_in_as'] == "carmen"