feat: increate minimum challenge requirement AB test (#44764)

* feat: increate minimum challenge requirement AB test

* fix: adjust tests

Co-authored-by: ahmad abdolsaheb <home@mac-16.local>
This commit is contained in:
Ahmad Abdolsaheb
2022-01-13 23:51:55 +03:00
committed by GitHub
parent 8f8a2cc0c5
commit e97920ae9c
6 changed files with 47 additions and 109 deletions

View File

@ -358,7 +358,7 @@
"one-time": "If you'd prefer to make one-time donations, you can support freeCodeCamp's mission whenever you have cash to spare. You can use <0>this link to donate whatever amount feels right through PayPal</0>.", "one-time": "If you'd prefer to make one-time donations, you can support freeCodeCamp's mission whenever you have cash to spare. You can use <0>this link to donate whatever amount feels right through PayPal</0>.",
"wire-transfer": "You can also send money to freeCodeCamp directly through a wire transfer. If you need our wire details, email Quincy at quincy@freecodecamp.org", "wire-transfer": "You can also send money to freeCodeCamp directly through a wire transfer. If you need our wire details, email Quincy at quincy@freecodecamp.org",
"does-crypto": "Does freeCodeCamp accept donations in Bitcoin or other cryptocurrencies?", "does-crypto": "Does freeCodeCamp accept donations in Bitcoin or other cryptocurrencies?",
"yes-crypto": "Yes, and we would welcome your cryptocurrency donations. Here are our wallet details:", "yes-cryptocurrency": "Yes. Please email Quincy at quincy@freecodecamp.org and he can send you freeCodeCamp's wallet information. He can also provide you with a donation receipt if you need one for your taxes.",
"can-check": "Can I mail a physical check?", "can-check": "Can I mail a physical check?",
"yes-check": "Yes, we would welcome a check. You can mail it to us at:", "yes-check": "Yes, we would welcome a check. You can mail it to us at:",
"how-matching-gift": "How can I set up matching gifts from my employer, or payroll deductions?", "how-matching-gift": "How can I set up matching gifts from my employer, or payroll deductions?",

View File

@ -2,24 +2,6 @@ import React, { useState } from 'react';
import { useTranslation, Trans } from 'react-i18next'; import { useTranslation, Trans } from 'react-i18next';
import Caret from '../../assets/icons/caret'; import Caret from '../../assets/icons/caret';
const WALLETS = (
<>
<code>Bitcoin: 3B4QShnJawtzBd1FFzHPpVCpxBpVbcbPRg</code>
<br />
<code>Ethereum: 0x1ee753faa97BE3C4b9b1dE775dB44c9Bfac0EC91</code>
<br />
<code>Litecoin: MVDLr18spSjd9nDyKG2Y94BFmgzbjXgfCD</code>
<br />
<code>Bitcoin Cash: qqw8lhpnu635za8f5c22ghynl6yz5zelp52t25lmnm</code>
<br />
<code>USD Coin: 0xad4f0c8363fE733DdbfEDBdAf6600E2b6dF2900d</code>
<br />
<code>DAI: 0xad4f0c8363fE733DdbfEDBdAf6600E2b6dF2900d</code>
<br />
<code>Dash: XyRp67PQVBRaZu2LJU6Ndc5kp3AaRaHnXt</code>
</>
);
const POBOX = ( const POBOX = (
<> <>
<code>Free Code Camp, Inc.</code> <code>Free Code Camp, Inc.</code>
@ -156,8 +138,7 @@ export const DonationFaqText = (): JSX.Element => {
Q: t('donate.does-crypto'), Q: t('donate.does-crypto'),
A: ( A: (
<> <>
<p>{t('donate.yes-crypto')}</p> <p>{t('donate.yes-cryptocurrency')}</p>
<p>{WALLETS}</p>
</> </>
) )
}, },

View File

@ -12,19 +12,12 @@ import DonateForm from '../components/Donation/donate-form';
import { import {
DonationText, DonationText,
DonationOptionsAlertText, DonationOptionsAlertText,
DonationSupportText,
DonationOptionsText,
DonationFaqText DonationFaqText
} from '../components/Donation/donation-text-components'; } from '../components/Donation/donation-text-components';
import { Spacer, Loader } from '../components/helpers'; import { Spacer, Loader } from '../components/helpers';
import CampersImage from '../components/landing/components/campers-image'; import CampersImage from '../components/landing/components/campers-image';
import { import { signInLoadingSelector, userSelector, executeGA } from '../redux';
signInLoadingSelector,
userSelector,
executeGA,
isAVariantSelector
} from '../redux';
export interface ExecuteGaArg { export interface ExecuteGaArg {
type: string; type: string;
@ -40,22 +33,15 @@ interface DonatePageProps {
executeGA: (arg: ExecuteGaArg) => void; executeGA: (arg: ExecuteGaArg) => void;
isDonating?: boolean; isDonating?: boolean;
showLoading: boolean; showLoading: boolean;
isAVariant: boolean;
t: TFunction; t: TFunction;
} }
const mapStateToProps = createSelector( const mapStateToProps = createSelector(
userSelector, userSelector,
signInLoadingSelector, signInLoadingSelector,
isAVariantSelector, ({ isDonating }: { isDonating: boolean }, showLoading: boolean) => ({
(
{ isDonating }: { isDonating: boolean },
showLoading: boolean,
isAVariant: boolean
) => ({
isDonating, isDonating,
showLoading, showLoading
isAVariant
}) })
); );
@ -67,7 +53,6 @@ function DonatePage({
executeGA = () => {}, executeGA = () => {},
isDonating = false, isDonating = false,
showLoading, showLoading,
isAVariant,
t t
}: DonatePageProps) { }: DonatePageProps) {
useEffect(() => { useEffect(() => {
@ -94,34 +79,6 @@ function DonatePage({
}); });
} }
const donationSupport = (
<>
<Row className='donate-support'>
<Col xs={12}>
<hr />
<DonationOptionsText />
<DonationSupportText />
</Col>
</Row>
</>
);
const donationFaq = (
<>
<Spacer size={3} />
<Row className='donate-support' id='FAQ'>
<Col className={'text-center'} xs={12}>
<hr />
<h2>{t('donate.faq')}</h2>
<Spacer />
</Col>
<Col xs={12}>
<DonationFaqText />
</Col>
</Row>
</>
);
return showLoading ? ( return showLoading ? (
<Loader fullScreen={true} /> <Loader fullScreen={true} />
) : ( ) : (
@ -155,7 +112,17 @@ function DonatePage({
<DonateForm handleProcessing={handleProcessing} /> <DonateForm handleProcessing={handleProcessing} />
</Col> </Col>
</Row> </Row>
{isAVariant ? donationSupport : donationFaq} <Spacer size={3} />
<Row className='donate-support' id='FAQ'>
<Col className={'text-center'} xs={12}>
<hr />
<h2>{t('donate.faq')}</h2>
<Spacer />
</Col>
<Col xs={12}>
<DonationFaqText />
</Col>
</Row>
</Col> </Col>
<Col lg={6}> <Col lg={6}>
<CampersImage pageName='donate' /> <CampersImage pageName='donate' />

View File

@ -231,6 +231,7 @@ export const shouldRequestDonationSelector = state => {
const canRequestProgressDonation = state[MainApp].canRequestProgressDonation; const canRequestProgressDonation = state[MainApp].canRequestProgressDonation;
const isDonating = isDonatingSelector(state); const isDonating = isDonatingSelector(state);
const recentlyClaimedBlock = recentlyClaimedBlockSelector(state); const recentlyClaimedBlock = recentlyClaimedBlockSelector(state);
const isAVariant = isAVariantSelector(state);
// don't request donation if already donating // don't request donation if already donating
if (isDonating) return false; if (isDonating) return false;
@ -243,9 +244,17 @@ export const shouldRequestDonationSelector = state => {
// donations only appear after the user has completed ten challenges (i.e. // donations only appear after the user has completed ten challenges (i.e.
// not before the 11th challenge has mounted) // not before the 11th challenge has mounted)
// the follwoing is an AB test for increasing the completed challenge requirement to 20
if (isAVariant) {
if (completedChallenges.length < 10) { if (completedChallenges.length < 10) {
return false; return false;
} }
} else {
if (completedChallenges.length < 20) {
return false;
}
}
// this will mean we have completed 3 or more challenges this browser session // this will mean we have completed 3 or more challenges this browser session
// and enough challenges overall to not be new // and enough challenges overall to not be new
return completionCount >= 3; return completionCount >= 3;

View File

@ -94,7 +94,7 @@ const patreonDefaultPledgeAmount = 500;
const aBTestConfig = { const aBTestConfig = {
isTesting: true, isTesting: true,
type: 'AddDonateFAQ' type: 'increaceChallengesCompleted'
}; };
module.exports = { module.exports = {

View File

@ -1,13 +1,3 @@
const selectors = {
donateSupport: {
firstTitle: '.donate-support h4:first-of-type b',
secondTitle: '.donate-support h4:last-of-type b',
firstText: '.donate-support p:first-of-type',
secondText: '.donate-support p:last-of-type',
link: '.donate-support a'
}
};
describe('Donate page', () => { describe('Donate page', () => {
before(() => { before(() => {
cy.clearCookies(); cy.clearCookies();
@ -24,40 +14,31 @@ describe('Donate page', () => {
cy.contains('Confirm your donation of $5 / month:').should('be.visible'); cy.contains('Confirm your donation of $5 / month:').should('be.visible');
}); });
it('Should have support section', () => { it('Should have FAQ section', () => {
cy.contains('Frequently asked questions');
cy.contains('How can I get help with my donations?');
cy.contains('How transparent is freeCodeCamp.org?');
cy.contains('How efficient is freeCodeCamp?');
cy.contains('How can I make a one-time donation?');
cy.contains( cy.contains(
'Want to make a bigger one-time donation, mail us a check, or give in other ways?' 'Does freeCodeCamp accept donations in Bitcoin or other cryptocurrencies?'
).should('be.visible'); );
}); cy.contains('Can I mail a physical check?');
it('Support section should have support text', () => {
cy.contains( cy.contains(
selectors.donateSupport.firstTitle, 'How can I set up matching gifts from my employer, or payroll deductions?'
'Want to make a bigger one-time donation, mail us a check, or give in other ways?' );
cy.contains('How can I set up an Endowment Gift to freeCodeCamp.org?');
cy.contains('How can I set up a Legacy gift to freeCodeCamp.org?').should(
'be.visible'
);
cy.contains('How can I donate stock to freeCodeCamp.org?').should(
'be.visible'
); );
cy.contains( cy.contains(
selectors.donateSupport.secondTitle, 'I set up a monthly donation, but I need to update or pause the monthly recurrence. How can I do this?'
'Need help with your current or past donations?'
); );
cy.contains( cy.contains(
selectors.donateSupport.firstText, 'Is there anything else I can learn about donating to freeCodeCamp.org?'
"Here are many other ways you can support our non-profit's mission."
); );
cy.contains(
selectors.donateSupport.secondText,
'Forward a copy of your donation receipt to donors@freecodecamp.org and tell us how we can help.'
);
});
it('Support section should have donation link', () => {
cy.get(selectors.donateSupport.link).should(
'have.attr',
'href',
'https://www.freecodecamp.org/news/how-to-donate-to-free-code-camp'
);
});
it('Donor alert should not be visible for non-donor', () => {
cy.get('.alert-info').should('not.exist');
}); });
}); });