Exemple #1
0
def test_talent_manager_can_get_company_feedback_stats_csv(
    ldap_mocked_app_with_users
):  # noqa: E501
    app = successfully_login(ldap_mocked_app_with_users, TEST_TALENT_MANAGER_USERNAME)
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession)
    response = app.get("/api/v1/company-feedback-stats.csv")
    assert response.content_type == "text/csv"
    assert response.body == open(TEST_CSV_FILEPATH, "rb").read()
Exemple #2
0
def test_talent_manager_can_get_company_raw_feedback(
    ldap_mocked_app_with_users
):  # noqa: E501
    app = successfully_login(ldap_mocked_app_with_users, TEST_TALENT_MANAGER_USERNAME)
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession)
    with transaction.manager:
        form = FeedbackForm(
            to_username=TEST_EMPLOYEE_3_USERNAME,
            from_username=TEST_TALENT_MANAGER_USERNAME,
            period_id=TEST_PREVIOUS_PERIOD_ID,
            is_summary=True,
        )
        answers = [
            FeedbackAnswer(question_id=QUESTION_IDS_AND_TEMPLATES[0][0], content="Foo"),
            FeedbackAnswer(question_id=QUESTION_IDS_AND_TEMPLATES[1][0], content="Bar"),
            FeedbackAnswer(question_id=QUESTION_IDS_AND_TEMPLATES[2][0], content="Tom"),
        ]
        form.answers = answers
        dbsession.add(form)
    response = app.get("/api/v1/company-raw-feedback.csv")
    assert response.content_type == "text/csv"
    num_q = 3
    nominee_1_answers = (
        (7 * num_q) + (3 * num_q) + (2 * num_q) + (TEST_NUM_FORMS_RECEIVED * num_q)
    )
    nominee_2_answers = 2 * num_q
    nominee_3_answers = (3 * num_q) + (8 * num_q) + (10 * num_q) + (2 * num_q)
    summary_answers = 3 * len(TEST_STATS_NOMINATED_USERS)
    num_expected = (
        nominee_1_answers + nominee_2_answers + nominee_3_answers + summary_answers
    )
    # remove csv header and trailing newline
    body = response.body.decode()
    num_generated = len(body.split("\n")) - 2
    assert num_expected == num_generated
    assert body.count(",True,") == summary_answers
    assert (
        body.count(
            "to_username,from_username,is_summary,name," "question_template,content"
        )
        == 1
    )
    raw_answer_row = (
        "{to_username},{from_username},True,{period_name},"
        "{template},{answer}"
        "".format(
            to_username=TEST_EMPLOYEE_3_USERNAME,
            from_username=TEST_TALENT_MANAGER_USERNAME,
            period_name=TEST_PREVIOUS_PERIOD_NAME,
            template=QUESTION_IDS_AND_TEMPLATES[1][1],
            answer="Bar",
        )
    )
    assert body.count(raw_answer_row) == 1
Exemple #3
0
def test_employee_can_view_feedback_received_for_all_periods(
        ldap_mocked_app_with_users):  # noqa: E501
    app = successfully_login(ldap_mocked_app_with_users,
                             TEST_EMPLOYEE_2_USERNAME)
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession)
    add_previous_test_summary(dbsession)
    add_extra_feedback_histories(dbsession, num=10)

    resp = app.get("/api/v1/feedback-about-me")
    assert len(resp.json_body["feedback"]["items"]) == 12

    items_payload = deepcopy(resp.json_body)
    items_payload["feedback"]["items"] = items_payload["feedback"]["items"][:2]
    assert EMPLOYEE_2_EXPECTED_HISTORY_HEAD == items_payload
Exemple #4
0
def test_employee_can_list_nominees_inside_entry_subperiod_2(
        ldap_mocked_app_with_users):  # noqa: E501
    """A particular DB state that caused failure in the past but
    is not working"""
    app = successfully_login(ldap_mocked_app_with_users,
                             TEST_EMPLOYEE_USERNAME)
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession, Period.ENTRY_SUBPERIOD)

    response = app.get("/api/v1/nominees")
    assert response.status_code == 200
    assert TEST_PERIOD_NAME == response.json_body["period"]
    # logged in user should not see their own name in nomination list
    nominees = [("bboggs", True), ("llovelace", False)]
    expected = []
    for un, has_manager_in_database in nominees:
        data = TEST_LDAP_FULL_DETAILS[un]
        un_name = data[TEST_USERNAME_KEY]
        # if they are not in the User database, then they don't exist so
        # can't put up a display name
        if has_manager_in_database:
            manager = TEST_LDAP_FULL_DETAILS.get(data[MANAGER_KEY])
            manager_display_name = " ".join(
                [manager["givenName"], manager["sn"]])
        else:
            manager_display_name = "-"
        expected.append({
            "username":
            un_name,
            "displayName":
            data["givenName"] + " " + data["sn"],
            "position":
            data["title"],
            "managerDisplayName":
            manager_display_name,
            "department":
            data["department"],
            "hasExistingFeedback":
            True if un_name == EXISTING_FEEDBACK_FORM_USERNAME else False,
        })

    sorted_response = sorted(response.json_body["nominees"],
                             key=lambda x: x["displayName"])
    assert len(expected) == len(sorted_response)
    assert expected == sorted_response
Exemple #5
0
def test_talent_manager_can_correct_summarised_feedback_from_another_manager(
    ldap_mocked_app_with_users
):  # noqa: E501
    app = successfully_login(ldap_mocked_app_with_users, TEST_TALENT_MANAGER_USERNAME)
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession, current_subperiod=Period.REVIEW_SUBPERIOD)
    response = app.get("/api/v1/summarise/%s/" % TEST_EMPLOYEE_2_USERNAME)
    items = response.json_body["summary"]["items"]
    expected = [
        {"questionId": QUESTION_IDS_AND_TEMPLATES[0][0], "answer": TEST_SUMMARY_1},
        {"questionId": QUESTION_IDS_AND_TEMPLATES[1][0], "answer": TEST_SUMMARY_2},
        {"questionId": QUESTION_IDS_AND_TEMPLATES[2][0], "answer": TEST_SUMMARY_3},
    ]
    generated = sorted(items, key=lambda k: k["questionId"])

    for exp, gen in zip(expected, generated):
        assert exp["questionId"] == gen["questionId"]
        assert exp["answer"] == gen["answer"]
Exemple #6
0
def test_hostname_override_works(ldap_mocked_app_with_users, ldapsource,
                                 with_envvar):
    app = ldap_mocked_app_with_users
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession,
                            current_subperiod=Period.ENROLLMENT_SUBPERIOD)
    displayed_hostname = "notfoobar.com"
    assert displayed_hostname != TEST_PRODUCTION_HOSTNAME
    settings = {
        "adaero.talent_manager_usernames": [TEST_OTHER_MANAGER_USERNAME],
        "adaero.served_on_https": True,
        "adaero.homebase_location": "London",
        "adaero.production_hostname": TEST_PRODUCTION_HOSTNAME,
        "adaero.production_user": TEST_PRODUCTION_USER,
        "adaero.enable_send_email": True,
    }

    if with_envvar:
        os.environ["DISPLAYED_HOSTNAME"] = displayed_hostname
    else:
        settings[DISPLAYED_HOSTNAME_KEY] = displayed_hostname

    with patch("smtplib.SMTP") as smtp_mock, patch(
            "socket.gethostname") as gethostname_mock, patch(
                "getpass.getuser") as getuser_mock:
        sendmail_mock = smtp_mock().sendmail
        gethostname_mock.return_value = TEST_PRODUCTION_HOSTNAME
        getuser_mock.return_value = TEST_PRODUCTION_USER
        mail.check_and_send_email(dbsession,
                                  ldapsource,
                                  settings,
                                  template_key=ENROL_START,
                                  force=True)

        generated_raw_message = sendmail_mock.call_args_list[0][0][2]
        normal_app_link = "https://%s" % TEST_PRODUCTION_HOSTNAME
        overridden_app_link = "https://%s" % displayed_hostname
        parser = Parser()
        message_root = parser.parsestr(generated_raw_message)
        messages = message_root.get_payload()
        plain = b64decode(messages[0].get_payload()).decode("utf-8")
        assert plain.count(normal_app_link) == 0
        assert plain.count(overridden_app_link) > 0
Exemple #7
0
def test_do_not_send_emails_when_not_in_production(ldap_mocked_app_with_users,
                                                   ldapsource):
    app = ldap_mocked_app_with_users
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession)
    settings = {
        "adaero.talent_manager_usernames": [TEST_TALENT_MANAGER_USERNAME],
        "adaero.homebase_location": "London",
    }

    with patch("smtplib.SMTP") as smtp_mock, patch(
            "socket.gethostname") as gethostname_mock, patch(
                "getpass.getuser") as getuser_mock:
        sendmail_mock = smtp_mock().sendmail
        gethostname_mock.return_value = "foo"
        getuser_mock.return_value = "bar"
        mail.check_and_send_email(dbsession,
                                  ldapsource,
                                  settings,
                                  delay_s=0,
                                  delay_between_s=0)
        assert 0 == len(sendmail_mock.call_args_list)
Exemple #8
0
def test_emailing_works_with_different_tm_username_config(
        ldap_mocked_app_with_users, ldapsource):  # noqa: E501
    app = ldap_mocked_app_with_users
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession)
    json_str = '["%s"]' % TEST_OTHER_MANAGER_USERNAME
    settings = {
        "adaero.talent_manager_usernames": json_str,
        "adaero.homebase_location": "London",
    }

    with patch("smtplib.SMTP") as smtp_mock, patch(
            "socket.gethostname") as gethostname_mock, patch(
                "getpass.getuser") as getuser_mock:
        sendmail_mock = smtp_mock().sendmail
        gethostname_mock.return_value = "foo"
        getuser_mock.return_value = "bar"
        mail.check_and_send_email(dbsession,
                                  ldapsource,
                                  settings,
                                  delay_s=0,
                                  delay_between_s=0)
        assert 0 == len(sendmail_mock.call_args_list)
Exemple #9
0
def test_get_summarised_users(ldap_mocked_app_with_users):
    app = ldap_mocked_app_with_users
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession)
    users = mail.get_summarised_users(dbsession)
    assert {u.username for u in users} == {k for k in SUMMARISED_USERNAMES}
Exemple #10
0
def test_send_emails_according_to_configured_location(
    ldap_mocked_app_with_users,  # noqa: E501
    ldapsource,
    subperiod,
    location,
    utc_offset_tuples,
):
    app = ldap_mocked_app_with_users
    dbsession = get_dbsession(app)
    # so date saved in database is TEST_UTCNOW
    freezer = freeze_time(TEST_UTCNOW)
    freezer.start()
    add_test_data_for_stats(dbsession, current_subperiod=subperiod, days_in=0)
    freezer.stop()
    # needs to be outside configured employees at a minimum
    settings = {
        "adaero.talent_manager_usernames": [TEST_OTHER_MANAGER_USERNAME],
        "adaero.served_on_https": True,
        "adaero.homebase_location": location,
        "adaero.enable_send_email": True,
    }

    with patch("smtplib.SMTP") as smtp_mock, patch(
            "socket.gethostname") as gethostname_mock, patch(
                "getpass.getuser") as getuser_mock:
        gethostname_mock.return_value = TEST_PRODUCTION_HOSTNAME
        sendmail_mock = smtp_mock().sendmail
        getuser_mock.return_value = TEST_PRODUCTION_USER
        date_ = TEST_UTCNOW.date()

        def check_sent(num, t):
            assert num == sendmail_mock.call_count, (
                "Incorrect number of emails sent for time %s" % t)

        for time_, num_sent in utc_offset_tuples:
            new_dt = datetime.combine(date_, time_)
            freezer = freeze_time(new_dt)

            freezer.start()
            mail.check_and_send_email(
                dbsession,
                ldapsource,
                settings,
                force=False,
                delay_s=0,
                delay_between_s=0,
            )
            check_sent(num_sent, time_)
            # email has already sent, won't send again
            mail.check_and_send_email(
                dbsession,
                ldapsource,
                settings,
                force=False,
                delay_s=0,
                delay_between_s=0,
            )
            check_sent(num_sent, time_)
            freezer.stop()
            sendmail_mock.reset_mock()

            period = Period.get_current_period(dbsession)
            period.enrol_email_last_sent = None
            period.enrol_reminder_email_last_sent = None
            period.entry_email_last_sent = None
            period.entry_reminder_email_last_sent = None
            period.review_email_last_sent = None
            period.feedback_available_mail_last_sent = None
            with transaction.manager:
                dbsession.merge(period)
Exemple #11
0
def test_send_correct_emails_are_sent_during_subperiods(
    ldap_mocked_app_with_users,  # noqa: E501
    ldapsource,
    subperiod,
    num_times,
    last_sent_email_code,
    last_sent_template_key,
    force,
    last_users,
):
    app = ldap_mocked_app_with_users
    dbsession = get_dbsession(app)
    add_test_data_for_stats(dbsession, current_subperiod=subperiod)
    settings = {
        "adaero.load_talent_managers_on_app_start": False,
        "adaero.talent_manager_usernames": [TEST_TALENT_MANAGER_USERNAME],
        "adaero.served_on_https": True,
        "adaero.homebase_location": "London",
        "adaero.production_hostname": TEST_PRODUCTION_HOSTNAME,
        "adaero.production_user": TEST_PRODUCTION_USER,
        "adaero.enable_send_email": True,
    }

    with patch("smtplib.SMTP") as smtp_mock, patch(
            "socket.gethostname") as gethostname_mock, patch(
                "getpass.getuser") as getuser_mock:
        sendmail_mock = smtp_mock().sendmail
        gethostname_mock.return_value = TEST_PRODUCTION_HOSTNAME
        getuser_mock.return_value = TEST_PRODUCTION_USER
        for i in range(num_times):
            kwargs = {"force": force, "delay_s": 0, "delay_between_s": 0}
            if force:
                kwargs["template_key"] = last_sent_template_key

            mail.check_and_send_email(dbsession, ldapsource, settings,
                                      **kwargs)

            if i < num_times - 1:
                sendmail_mock.reset_mock()
        with transaction.manager:
            period = Period.get_current_period(dbsession)

            assert period.get_email_flag_by_code(
                last_sent_email_code) == TEST_UTCNOW
            for code in EMAIL_CODES.difference({last_sent_email_code}):
                assert period.get_email_flag_by_code(code) != TEST_UTCNOW

        if not len(last_users):
            assert 0 == len(sendmail_mock.call_args_list)
            return

        # TODO: why is email a list now?
        confirm_email_call = sendmail_mock.call_args_list.pop(-1)
        normal_emails_calls = sorted(sendmail_mock.call_args_list,
                                     key=lambda c: c[0][1][0])
        sorted_by_email_users = sorted(last_users, key=lambda v: v["mail"])
        app_link = "https://%s" % TEST_PRODUCTION_HOSTNAME

        assert len(normal_emails_calls) == len(
            normal_emails_calls), "Incorrect number of normal emails sent"

        parser = Parser()

        # normal_emails_calls = sorted_by_email_calls[:-1]
        # confirm_email_call = sorted_by_email_calls[-1]
        for u, c in zip(sorted_by_email_users, normal_emails_calls):
            args = c[0]
            assert u["mail"] == args[1][0]
            generated_raw_message = args[2]
            message_root = parser.parsestr(generated_raw_message)
            messages = message_root.get_payload()
            assert len(messages) == 2
            plain = b64decode(messages[0].get_payload()).decode("utf-8")
            html = b64decode(messages[1].get_payload()).decode("utf-8")
            # assert no non interpolated variables
            assert plain.count("{") == 0
            assert plain.count(u["givenName"]) > 0
            assert plain.count(app_link) > 0

            assert html.count("{") == 0
            assert html.count(u["givenName"]) > 0
            assert html.count(app_link) > 1
            assert html.count(app_link) % 2 == 0
            assert html.count("</html>") == 1

        num_normal_emails = len(normal_emails_calls)
        tm_details = TEST_LDAP_FULL_DETAILS[TEST_TALENT_MANAGER_USERNAME]
        assert tm_details["mail"] == confirm_email_call[0][1][0]

        # Deal with confirm email sent to talent managers
        confirm_raw_message = confirm_email_call[0][2]
        confirm_root = parser.parsestr(confirm_raw_message)
        confirm_messages = confirm_root.get_payload()
        assert len(confirm_messages) == 2

        confirm_plain = b64decode(
            confirm_messages[0].get_payload()).decode("utf-8")
        confirm_html = b64decode(
            confirm_messages[1].get_payload()).decode("utf-8")

        for m in [confirm_plain, confirm_html]:
            assert m.count(
                EMAIL_TEMPLATE_MAP[last_sent_template_key]["summary"]) == 1
            # exclude confirmation email from count
            assert m.count("%s email addresses" % num_normal_emails) == 1
        assert confirm_html.count("</html>") == 1