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:
@ -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?",
|
||||||
|
@ -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>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -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' />
|
||||||
|
@ -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)
|
||||||
if (completedChallenges.length < 10) {
|
// the follwoing is an AB test for increasing the completed challenge requirement to 20
|
||||||
return false;
|
if (isAVariant) {
|
||||||
|
if (completedChallenges.length < 10) {
|
||||||
|
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;
|
||||||
|
@ -94,7 +94,7 @@ const patreonDefaultPledgeAmount = 500;
|
|||||||
|
|
||||||
const aBTestConfig = {
|
const aBTestConfig = {
|
||||||
isTesting: true,
|
isTesting: true,
|
||||||
type: 'AddDonateFAQ'
|
type: 'increaceChallengesCompleted'
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -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');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user