Exemple #1
0
def test_profile_updates_name_and_bio_not_email(client: Client, user: User) -> None:
    resp = client.get("/test-login/{}".format(user.user_id), follow_redirects=True)
    resp = client.get("/profile")
    assert_html_response_contains(
        resp,
        re.compile('<input[^>]*name="fullname"'),
        re.compile('<input[^>]*id="email"[^>]*disabled'),
        re.compile('<textarea[^>]*name="speaker_bio"'),
    )

    csrf_token = extract_csrf_from(resp)
    postdata = {
        "email": "*****@*****.**",
        "fullname": "Jane Doe",
        "speaker_bio": "This is Jane's biography.",
        "csrf_token": csrf_token,
    }
    resp = client.post("/profile", data=postdata, follow_redirects=True)
    assert_html_response_contains(resp, "Talks")

    db.session.add(user)
    db.session.refresh(user)
    assert user.fullname == "Jane Doe"
    assert user.speaker_bio == "This is Jane's biography."
    assert user.email == "*****@*****.**"  # the old address
Exemple #2
0
def test_inviting_a_speaker_adds_the_speaker(client: Client, user: User,
                                             send_mail: Mock) -> None:
    talk = Talk(title="My Talk", length=25)
    talk.add_speaker(user, InvitationStatus.CONFIRMED)
    db.session.add(talk)

    alice = User(email="*****@*****.**", fullname="Alice Example")
    db.session.add(alice)
    db.session.commit()

    # reload from DB to avoid "not attached to session" error
    talk = Talk.query.filter_by(title="My Talk").one()

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks/{}/speakers".format(talk.talk_id))
    assert_html_response(resp)
    csrf_token = extract_csrf_from(resp)

    postdata = {"email": "*****@*****.**", "csrf_token": csrf_token}
    resp = client.post("/talks/{}/speakers".format(talk.talk_id),
                       data=postdata,
                       follow_redirects=True)

    assert_html_response_contains(resp, "Alice Example")

    send_mail.assert_called_once_with(to=["*****@*****.**"],
                                      template="email/co-presenter-invite",
                                      talk=ANY)

    _, kwargs = send_mail.call_args
    assert kwargs["talk"].talk_id == talk.talk_id

    assert_talk_has_speakers(talk, ["*****@*****.**"])
Exemple #3
0
def test_demographic_survey_skips_blank_other_values(
    client: Client, user: User
) -> None:
    assert user.demographic_survey is None

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/profile/demographic_survey")

    assert_html_response_contains(
        resp,
        "I identify as a:",
        "I identify my ethnicity as:",
        "About my past speaking experience:",
        "My age is:",
        "I have been programming for:",
    )

    csrf_token = extract_csrf_from(resp)
    postdata = {"gender": ["MAN", ""], "csrf_token": csrf_token}
    resp = client.post(
        "/profile/demographic_survey", data=postdata, follow_redirects=True
    )
    assert_html_response_contains(resp, "Thanks For Completing")

    survey = DemographicSurvey.query.filter_by(user_id=user.user_id).one()

    assert survey.gender == ["MAN"]
Exemple #4
0
def test_inviting_a_speaker_emails_the_speaker(client: Client, user: User,
                                               send_mail: Mock) -> None:
    talk = Talk(title="My Talk", length=25)
    talk.add_speaker(user, InvitationStatus.CONFIRMED)
    db.session.add(talk)
    db.session.commit()

    assert User.query.filter_by(
        email="*****@*****.**").one_or_none() is None

    # reload from DB to avoid "not attached to session" error
    talk = Talk.query.filter_by(title="My Talk").one()

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks/{}/speakers".format(talk.talk_id))
    assert_html_response(resp)
    csrf_token = extract_csrf_from(resp)

    # this speaker doesn't exist, but we should still send the email
    postdata = {"email": "*****@*****.**", "csrf_token": csrf_token}
    resp = client.post("/talks/{}/speakers".format(talk.talk_id),
                       data=postdata,
                       follow_redirects=True)

    assert_html_response_contains(resp, "*****@*****.**")

    send_mail.assert_called_once_with(to=["*****@*****.**"],
                                      template="email/co-presenter-invite",
                                      talk=ANY)

    _, kwargs = send_mail.call_args
    assert kwargs["talk"].talk_id == talk.talk_id

    # this also implies a user with that email was created
    assert_talk_has_speakers(talk, ["*****@*****.**"])
Exemple #5
0
def test_vote_review_shows_your_vote_and_conduct_form(
    *,
    vote_value: Optional[int],
    skipped: bool,
    vote_note: str,
    authenticated_client: Client,
    user: User,
) -> None:
    """Show the user's vote results, if present, and the conduct report form."""
    talk = Talk(
        title="",
        length=1,
        is_anonymized=True,
        anonymized_title="",
        anonymized_description="",
        anonymized_outline="",
        anonymized_take_aways="",
    )
    conference = Conference.query.first()
    category = Category(name="", conference=conference)
    category.talks.append(talk)
    db.session.add_all((category, talk))
    if vote_value is not None:
        vote = Vote(talk=talk, user=user, value=vote_value, skipped=False)
        db.session.add(vote)
    elif skipped:
        vote = Vote(talk=talk, user=user, value=None, skipped=True)
        db.session.add(vote)
    db.session.commit()

    resp = authenticated_client.get(f"/review/{talk.talk_id}")
    assert_html_response_contains(resp, vote_note)
    assert_html_response_contains(
        resp, '<form method="POST" action="/conduct-report">')
Exemple #6
0
def test_talk_form_uses_select_field_for_length(client: Client, user: User) -> None:
    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks/new")

    assert_html_response_contains(
        resp,
        re.compile(
            '<select[^>]*(?:name="length"[^>]*required|required[^>]*name="length")'
        ),
    )
Exemple #7
0
def test_demographic_survey_saves_data(client: Client, user: User) -> None:
    assert user.demographic_survey is None

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/profile/demographic_survey")

    assert_html_response_contains(
        resp,
        "I identify as a:",
        "I identify my ethnicity as:",
        "About my past speaking experience:",
        "My age is:",
        "I have been programming for:",
    )

    csrf_token = extract_csrf_from(resp)
    postdata = {
        "gender": ["MAN", "WOMAN", "NONBINARY", "free form text for 'other' gender"],
        "ethnicity": [
            "ASIAN",
            "BLACK_AFRICAN_AMERICAN",
            "HISPANIC_LATINX",
            "NATIVE_AMERICAN",
            "PACIFIC_ISLANDER",
            "WHITE_CAUCASIAN",
            "free form text for 'other' ethnicity",
        ],
        "past_speaking": [
            "NEVER",
            "PYCONCA",
            "OTHER_PYTHON",
            "OTHER_NONPYTHON",
        ],
        "age_group": "UNDER_45",
        "programming_experience": "UNDER_10YR",
        "csrf_token": csrf_token,
    }
    resp = client.post(
        "/profile/demographic_survey", data=postdata, follow_redirects=True
    )
    assert_html_response_contains(resp, "Thanks For Completing")

    survey = DemographicSurvey.query.filter_by(user_id=user.user_id).one()

    assert sorted(survey.gender) == sorted(postdata["gender"])
    assert sorted(survey.ethnicity) == sorted(postdata["ethnicity"])
    assert sorted(survey.past_speaking) == sorted(postdata["past_speaking"])
    assert survey.age_group == AgeGroup.UNDER_45
    assert survey.programming_experience == ProgrammingExperience.UNDER_10YR
Exemple #8
0
def test_talk_anonymization(client: Client, user: User,
                            send_mail: Mock) -> None:
    user.site_admin = True
    db.session.add(user)

    talk = Talk(
        title="Alice's Identifying Talk",
        description="This talk is by Alice",
        outline="Alice!",
        take_aways="Alice's point.",
        length=25,
    )
    talk.add_speaker(user, InvitationStatus.CONFIRMED)
    db.session.add(talk)
    db.session.commit()

    db.session.refresh(talk)

    client.get("/test-login/{}".format(user.user_id), follow_redirects=True)
    resp = client.get(f"/manage/anonymize/{talk.talk_id}")
    assert_html_response_contains(resp, "Alice&#x27;s Identifying Talk")

    postdata = {
        "title": "(Speaker name redacted)'s Identifying Talk",
        "description": "This talk is by (Speaker name redacted)",
        "outline": "(Speaker name redacted)!",
        "take_aways": "(The speaker's) point.",
        "csrf_token": extract_csrf_from(resp),
    }
    client.post(f"/manage/anonymize/{talk.talk_id}", data=postdata)

    talk = Talk.query.get(talk.talk_id)
    assert talk.is_anonymized is True
    assert talk.has_anonymization_changes is True
    assert talk.anonymized_title == "(Speaker name redacted)'s Identifying Talk"
    assert talk.anonymized_description == "This talk is by (Speaker name redacted)"
    assert talk.anonymized_outline == "(Speaker name redacted)!"
    assert talk.anonymized_take_aways == "(The speaker's) point."
    assert talk.title == "Alice's Identifying Talk"
    assert talk.description == "This talk is by Alice"
    assert talk.outline == "Alice!"
    assert talk.take_aways == "Alice's point."

    send_mail.assert_called_once_with(
        to=[user.email],
        template="email/talk-anonymized",
        talk_id=talk.talk_id,
        title=talk.title,  # the original title
    )
Exemple #9
0
def test_demographic_survey_opt_out(client: Client, user: User) -> None:
    assert user.demographic_survey is None

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/profile/demographic_survey/opt-out")

    assert_html_response_contains(resp, "You Have Opted Out")

    survey = DemographicSurvey.query.filter_by(user_id=user.user_id).one()

    assert not survey.gender
    assert not survey.ethnicity
    assert not survey.age_group
    assert not survey.programming_experience
    assert not survey.past_speaking
Exemple #10
0
def test_email_magic_link_form(client: Client, send_mail: Mock) -> None:
    resp = client.get("/login/email")
    assert_html_response_contains(resp, re.compile('<input.*name="email"'))
    csrf_token = extract_csrf_from(resp)

    postdata = {"email": "*****@*****.**", "csrf_token": csrf_token}
    resp = client.post("/login/email", data=postdata, follow_redirects=True)

    assert_html_response_contains(resp, "We have sent a link to you")
    send_mail.assert_called_once_with(
        to=["*****@*****.**"],
        template="email/magic-link",
        magic_link=ANY,
        magic_link_expiration="30 minutes",
    )
Exemple #11
0
def test_prompt_for_demographic_survey(client: Client, user: User) -> None:
    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks")

    assert_html_response_doesnt_contain(resp, "demographic survey")

    talk = Talk(title="My Talk", length=25)
    talk.add_speaker(user, InvitationStatus.CONFIRMED)
    db.session.add(talk)
    db.session.commit()

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks")

    assert_html_response_contains(resp, "demographic_survey")
Exemple #12
0
def test_speakers_button_shows_up_on_existing_talks(client: Client,
                                                    user: User) -> None:
    talk = Talk(title="My Talk", length=25)
    talk.add_speaker(user, InvitationStatus.CONFIRMED)
    db.session.add(talk)
    db.session.commit()

    # reload from DB to avoid "not attached to session" error
    talk = Talk.query.filter_by(title="My Talk").one()

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks/{}".format(talk.talk_id))

    assert_html_response_contains(
        resp,
        re.compile('<a href="/talks/{}/speakers".*class=".*btn.*">'
                   "Manage Speakers</a>".format(talk.talk_id)),
    )
Exemple #13
0
def test_accept_button_accepts_the_talk(client: Client, user: User) -> None:
    alice = User(email="*****@*****.**", fullname="Alice Example")
    db.session.add(alice)

    talk = Talk(title="My Talk", length=25)
    talk.add_speaker(alice, InvitationStatus.CONFIRMED)  # original speaker
    talk.add_speaker(user, InvitationStatus.PENDING)
    db.session.add(talk)
    db.session.commit()

    client.get("/test-login/{}".format(user.user_id))
    client.get("/talks/1/speakers/accept")
    resp = client.get("/talks")

    assert_html_response_contains(resp, "My Talk",
                                  "(25 Minutes, Alice Example and You)")
    assert_html_response_doesnt_contain(resp, "Speaker Invitations:", "Reject",
                                        "Accept")
Exemple #14
0
def test_create_talk_goes_to_preview(client: Client, user: User) -> None:
    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks/new")
    csrf_token = extract_csrf_from(resp)

    postdata = {"title": "My Awesome Talk", "length": "25", "csrf_token": csrf_token}

    resp = client.post("/talks/new", data=postdata, follow_redirects=True)
    assert_html_response_contains(
        resp,
        "Reviewers will see voting instructions here",
        "Save &amp; Return",
        "Edit Again",
    )

    # but at this point the talk is saved
    speakers_predicate = Talk.speakers.any(user_id=user.user_id)  # type: ignore
    talks = Talk.query.filter(speakers_predicate).all()
    assert len(talks) == 1
    assert talks[0].title == "My Awesome Talk"
Exemple #15
0
def test_talks_list_shows_invitations(client: Client, user: User) -> None:
    alice = User(email="*****@*****.**", fullname="Alice Example")
    db.session.add(alice)

    talk = Talk(title="My Talk", length=25)
    talk.add_speaker(alice, InvitationStatus.CONFIRMED)  # original speaker
    talk.add_speaker(user, InvitationStatus.PENDING)
    db.session.add(talk)
    db.session.commit()

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/talks")

    assert_html_response_contains(
        resp,
        "Speaker Invitations:",
        "My Talk",
        "(25 Minutes, Alice Example and You)",
        '<a href="/talks/1/speakers/reject" class="btn btn-outline-danger btn-sm">Reject</a>',  # NOQA: B950
        '<a href="/talks/1/speakers/accept" class="btn btn-outline-primary btn-sm">Accept</a>',  # NOQA: B950
    )
Exemple #16
0
def test_talk_anonymization_doesnt_set_is_anonymized_if_no_changes(
        client: Client, user: User, send_mail: Mock) -> None:
    user.site_admin = True
    db.session.add(user)

    talk = Talk(
        title="Alice's Identifying Talk",
        description="This talk is by Alice",
        outline="Alice!",
        take_aways="Alice's point.",
        length=25,
    )
    talk.add_speaker(user, InvitationStatus.CONFIRMED)
    db.session.add(talk)
    db.session.commit()

    db.session.refresh(talk)

    client.get("/test-login/{}".format(user.user_id), follow_redirects=True)
    resp = client.get(f"/manage/anonymize/{talk.talk_id}")
    assert_html_response_contains(resp, "Alice&#x27;s Identifying Talk")

    postdata = {
        "title": talk.title,
        "description": talk.description,
        "outline": talk.outline,
        "take_aways": talk.take_aways,
        "csrf_token": extract_csrf_from(resp),
    }
    client.post(f"/manage/anonymize/{talk.talk_id}", data=postdata)

    talk = Talk.query.get(talk.talk_id)
    assert talk.is_anonymized is True
    assert talk.has_anonymization_changes is False
    assert talk.anonymized_title == talk.title
    assert talk.anonymized_description == talk.anonymized_description
    assert talk.anonymized_outline == talk.outline
    assert talk.anonymized_take_aways == talk.take_aways

    assert not send_mail.called
Exemple #17
0
def test_demographic_survey_bug_with_age_field(client: Client, user: User) -> None:
    # see https://gitlab.com/bigapplepy/yak-bak/issues/29
    assert user.demographic_survey is None

    client.get("/test-login/{}".format(user.user_id))
    resp = client.get("/profile/demographic_survey")

    csrf_token = extract_csrf_from(resp)
    postdata = {
        "age_group": "UNDER_45",
        "programming_experience": "UNDER_10YR",
        "csrf_token": csrf_token,
    }
    resp = client.post(
        "/profile/demographic_survey", data=postdata, follow_redirects=True
    )
    assert_html_response_contains(resp, "Thanks For Completing")

    resp = client.get("/profile/demographic_survey")
    assert_html_response_contains(
        resp,
        re.compile('<input checked[^>]* value="UNDER_45">'),
        re.compile('<input checked[^>]* value="UNDER_10YR">'),
    )
Exemple #18
0
def test_profile_lets_you_delete_speaker_bio(client: Client, user: User) -> None:
    user.speaker_bio = "This is the speaker bio"
    db.session.add(user)
    db.session.commit()

    client.get("/test-login/{}".format(user.user_id), follow_redirects=True)
    resp = client.get("/profile")
    assert_html_response_contains(resp, "This is the speaker bio")

    csrf_token = extract_csrf_from(resp)
    postdata = {
        "email": "*****@*****.**",
        "fullname": "Jane Doe",
        "speaker_bio": "",
        "csrf_token": csrf_token,
    }
    resp = client.post("/profile", data=postdata, follow_redirects=True)
    assert_html_response_contains(resp, "Talks")

    db.session.add(user)
    db.session.refresh(user)
    assert user.fullname == "Jane Doe"
    assert user.speaker_bio == ""
    assert user.email == "*****@*****.**"  # the old address
Exemple #19
0
def test_root_shows_cfp_description_when_logged_out(client: Client) -> None:
    resp = client.get("/")
    assert_html_response_contains(resp, "Our Call for Proposals is open through")
Exemple #20
0
def test_email_magic_link_login_for_returning_user(client: Client, user: User) -> None:
    with patch.object(views, "parse_magic_link_token") as parse:
        parse.return_value = user.email
        resp = client.get("/login/token/any-token-here", follow_redirects=True)

    assert_html_response_contains(resp, "Talks")
Exemple #21
0
def test_email_magic_link_login_for_new_user(client: Client) -> None:
    with patch.object(views, "parse_magic_link_token") as parse:
        parse.return_value = "*****@*****.**"
        resp = client.get("/login/token/any-token-here", follow_redirects=True)

    assert_html_response_contains(resp, "User Profile")
Exemple #22
0
def test_talks_list_shows_user_name(client: Client, user: User) -> None:
    resp = client.get("/test-login/{}".format(user.user_id), follow_redirects=True)
    assert_html_response_contains(resp, f"Log Out ({user.fullname})")
Exemple #23
0
def test_login_shows_auth_methods(client: Client) -> None:
    # only the email auth method is enabled in test config :\
    resp = client.get("/login")
    assert_html_response_contains(resp, "Magic Link")
Exemple #24
0
def test_logout_logs_you_out(client: Client, user: User) -> None:
    resp = client.get("/test-login/{}".format(user.user_id), follow_redirects=True)
    assert_html_response_contains(resp, f"Log Out ({user.fullname})")

    resp = client.get("/logout", follow_redirects=True)
    assert_html_response_contains(resp, "Log In")