예제 #1
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, ["*****@*****.**"])
예제 #2
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, ["*****@*****.**"])
예제 #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"]
예제 #4
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
예제 #5
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
    )
예제 #6
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
예제 #7
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",
    )
예제 #8
0
def test_talk_editing_not_allowed_while_voting(user: User,
                                               client: Client) -> None:
    conf = Conference.query.get(1)
    conf.voting_begin = datetime.utcnow() - timedelta(days=1)
    conf.voting_end = datetime.utcnow() + timedelta(days=1)
    db.session.add(conf)

    talk = Talk(title="My Talk", 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"/talks/{talk.talk_id}")
    assert_html_response(resp, status=200)

    postdata = {"csrf_token": extract_csrf_from(resp)}
    resp = client.post(f"/talks/{talk.talk_id}", data=postdata)
    assert_html_response(resp, status=400)
예제 #9
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"
예제 #10
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
예제 #11
0
def test_email_magic_link_tokens_only_work_once(
    client: Client, send_mail: Mock
) -> None:
    resp = client.get("/login/email")
    csrf_token = extract_csrf_from(resp)

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

    _, kwargs = send_mail.call_args
    magic_link_url = kwargs["magic_link"]
    assert not urlparse(magic_link_url).query

    magic_link_path = urlparse(magic_link_url).path

    # first time should work
    resp = client.get(magic_link_path)
    assert_redirected(resp, "/profile")  # new user, go to profile

    # second time should get a 401
    resp = client.get(magic_link_path)
    assert_html_response(resp, status=401)
예제 #12
0
def test_saving_a_talk_clears_categories(
    client: Client, conference: Conference, user: User
) -> None:
    category = Category(conference=conference, name="The Category")
    talk = Talk(title="Old Title", length=25)
    talk.categories.append(category)
    talk.add_speaker(user, InvitationStatus.CONFIRMED)
    db.session.add(talk)
    db.session.add(category)
    db.session.commit()

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

    csrf_token = extract_csrf_from(resp)
    postdata = {"title": "New Title", "csrf_token": csrf_token}
    resp = client.post("/talks/1", data=postdata, follow_redirects=True)
    assert_html_response(resp, status=200)

    talk = Talk.query.first()
    assert talk.title == "New Title"
    assert talk.categories == []
예제 #13
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">'),
    )
예제 #14
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