diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json index 4613d999fe6..036f9b6a1c9 100644 --- a/client/i18n/locales/english/translations.json +++ b/client/i18n/locales/english/translations.json @@ -401,21 +401,7 @@ "welcome-1": "Welcome back, {{name}}.", "welcome-2": "Welcome to freeCodeCamp.org", "start-at-beginning": "If you are new to coding, we recommend you <0>start at the beginning.", - "read-this": { - "heading": "Please slow down and read this.", - "p1": "freeCodeCamp is a proven path to your first software developer job.", - "p2": "More than 40,000 people have gotten developer jobs after completing this – including at big companies like Google and Microsoft.", - "p3": "If you are new to programming, we recommend you start at the beginning and earn these certifications in order.", - "p4": "To earn each certification, build its 5 required projects and get all their tests to pass.", - "p5": "You can add these certifications to your résumé or LinkedIn. But more important than the certifications is the practice you get along the way.", - "p6": "If you feel overwhelmed, that is normal. Programming is hard.", - "p7": "Practice is the key. Practice, practice, practice.", - "p8": "And this curriculum will give you thousands of hours of hands-on programming practice.", - "p9": "And if you want to learn more math and computer science theory, we also have thousands of hours of video courses on <0>freeCodeCamp's YouTube channel.", - "p10": "If you want to get a developer job or freelance clients, programming skills will be just part of the puzzle. You also need to build your personal network and your reputation as a developer.", - "p11": "You can do this on LinkedIn and GitHub, and also on <0>the freeCodeCamp forum.", - "p12": "Happy coding!" - }, + "happy-coding": "Happy coding!", "upcoming-lessons": "Upcoming Lessons", "learn": "Learn", "add-subtitles": "Help improve or add subtitles", @@ -795,7 +781,7 @@ "brand-new-account": "Welcome to your brand new freeCodeCamp account. Let's get started.", "duplicate-account-warning": "If you meant to sign into an existing account instead of creating this account, <0>click here to delete this account and try another email address.", "quincy": "- Quincy Larson, the teacher who founded freeCodeCamp.org", - "email-blast": "By the way, each Friday I send an email with 5 links about programming and computer science. I send these to about 6 million people. Would you like me to send this to you, too?", + "email-blast": "Each Friday I send an email with 5 links about programming and computer science. I send these to about 6 million people. Would you like me to send this to you, too?", "update-email-1": "Update your email address", "update-email-2": "Update your email address here:", "email": "Email", diff --git a/client/src/components/Intro/components/intro-description.tsx b/client/src/components/Intro/components/intro-description.tsx deleted file mode 100644 index 3360bfb3b7a..00000000000 --- a/client/src/components/Intro/components/intro-description.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import { Trans, useTranslation } from 'react-i18next'; -import { Spacer } from '@freecodecamp/ui'; -import envData from '../../../../config/env.json'; -import { Link } from '../../helpers'; - -import '../intro.css'; - -const { forumLocation } = envData; -function IntroDescription(): JSX.Element { - const { t } = useTranslation(); - - return ( -
- -

- {t('learn.read-this.heading')} -

- - {[...Array(8).keys()].map(i => ( -

- {t(`learn.read-this.p${i + 1}`)} -

- ))} -

- - - -

-

- {t('learn.read-this.p10')} -

-

- - - -

-

- {t('learn.read-this.p12')} -

- {t('misc.quincy')} -
- ); -} - -IntroDescription.displayName = 'IntroDescription'; - -export default IntroDescription; diff --git a/client/src/components/Intro/index.tsx b/client/src/components/Intro/index.tsx index f1caff9e423..7b5758186e8 100644 --- a/client/src/components/Intro/index.tsx +++ b/client/src/components/Intro/index.tsx @@ -4,7 +4,6 @@ import { Spacer } from '@freecodecamp/ui'; import { randomQuote } from '../../utils/get-words'; import Login from '../Header/components/login'; import { Link, Loader } from '../helpers'; -import IntroDescription from './components/intro-description'; import './intro.css'; import LearnAlert from './learn-alert'; @@ -83,16 +82,10 @@ const Intro = ({ return ( <> -

+

{t('learn.heading')}

- - {t('buttons.logged-out-cta-btn')} diff --git a/client/src/components/Intro/intro.css b/client/src/components/Intro/intro.css index f495ed716b7..ea8b5c064b6 100644 --- a/client/src/components/Intro/intro.css +++ b/client/src/components/Intro/intro.css @@ -24,7 +24,6 @@ border: none; } -.intro-description strong, .intro-description p { font-size: 1.17rem; } @@ -35,7 +34,6 @@ border: none; } - .intro-description strong, .intro-description p { font-size: 1rem; } diff --git a/client/src/components/landing/components/faq.tsx b/client/src/components/landing/components/faq.tsx index 151acf39f57..f1bd00cff3d 100644 --- a/client/src/components/landing/components/faq.tsx +++ b/client/src/components/landing/components/faq.tsx @@ -37,7 +37,7 @@ const Faq = (): JSX.Element => { ))} -

{t('learn.read-this.p12')}

+

{t('learn.happy-coding')}

diff --git a/client/src/pages/email-sign-up.tsx b/client/src/pages/email-sign-up.tsx index a5860edca6c..8f9cf350de6 100644 --- a/client/src/pages/email-sign-up.tsx +++ b/client/src/pages/email-sign-up.tsx @@ -7,7 +7,6 @@ import type { Dispatch } from 'redux'; import { createSelector } from 'reselect'; import { Container, Col, Row, Button, Spacer } from '@freecodecamp/ui'; -import IntroDescription from '../components/Intro/components/intro-description'; import createRedirect from '../components/create-redirect'; import { Loader, Link } from '../components/helpers'; import { apiLocation } from '../../config/env.json'; @@ -115,6 +114,7 @@ function AcceptPrivacyTerms({ const { t } = useTranslation(); const acceptedPrivacyRef = useRef(acceptedPrivacyTerms); const acceptTermsRef = useRef(acceptTerms); + const newAccount = isSignedIn && completedChallengeCount < 1; useEffect(() => { acceptedPrivacyRef.current = acceptedPrivacyTerms; @@ -130,29 +130,29 @@ function AcceptPrivacyTerms({ {t('misc.email-signup')} | freeCodeCamp.org - {isSignedIn && completedChallengeCount < 1 ? ( + + + +

+ {newAccount + ? t('misc.brand-new-account') + : t('misc.email-signup')} +

+ + +
+ {newAccount && ( - -

{t('misc.brand-new-account')}

-

+
- ) : ( - '' )} - - - - -
- -
diff --git a/e2e/learn.spec.ts b/e2e/learn.spec.ts index 904a002f2a8..0c88bcb3535 100644 --- a/e2e/learn.spec.ts +++ b/e2e/learn.spec.ts @@ -18,23 +18,6 @@ test.describe('Learn - Unauthenticated user', () => { }) ).toBeVisible(); - // Advice for new learners - const learnReadThisSection = page.getByTestId('learn-read-this-section'); - await expect(learnReadThisSection).toBeVisible(); - - const learnReadThisSectionHeading = page.getByTestId( - 'learn-read-this-heading' - ); - await expect(learnReadThisSectionHeading).toBeVisible(); - - const learnReadThisSectionParagraphs = - page.getByTestId('learn-read-this-p'); - await expect(learnReadThisSectionParagraphs).toHaveCount(10); - - for (const paragraph of await learnReadThisSectionParagraphs.all()) { - await expect(paragraph).toBeVisible(); - } - await expect( page.getByRole('link', { name: 'Sign in to save your progress' }) ).toBeVisible(); diff --git a/e2e/quincy-email-sign-up.spec.ts b/e2e/quincy-email-sign-up.spec.ts index 1ee51c19aed..20e09fa3b68 100644 --- a/e2e/quincy-email-sign-up.spec.ts +++ b/e2e/quincy-email-sign-up.spec.ts @@ -7,24 +7,6 @@ import { allowTrailingSlash } from './utils/url'; const apiLocation = process.env.API_LOCATION || 'http://localhost:3000'; -const contents = [ - translations.learn['read-this'].heading, - translations.learn['read-this'].p1, - translations.learn['read-this'].p2, - translations.learn['read-this'].p3, - translations.learn['read-this'].p4, - translations.learn['read-this'].p5, - translations.learn['read-this'].p6, - translations.learn['read-this'].p7, - translations.learn['read-this'].p8, - "And if you want to learn more math and computer science theory, we also have thousands of hours of video courses on freeCodeCamp's YouTube channel.", - translations.learn['read-this'].p10, - 'You can do this on LinkedIn and GitHub, and also on the freeCodeCamp forum.', - translations.learn['read-this'].p12, - translations.misc.quincy, - translations.misc['email-blast'] -]; - test.describe('Email sign-up page when user is not signed in', () => { test.use({ storageState: { cookies: [], origins: [] } }); @@ -33,25 +15,20 @@ test.describe('Email sign-up page when user is not signed in', () => { }); test('should display the content correctly', async ({ page }) => { - for (const content of contents) { - await expect(page.getByText(content)).toBeVisible(); - } - - const youtubeLink = page.getByRole('link', { - name: "freeCodeCamp's YouTube channel" - }); - await expect(youtubeLink).toHaveAttribute( - 'href', - 'https://youtube.com/freecodecamp' - ); - - const forumLink = page.getByRole('link', { - name: 'the freeCodeCamp forum' - }); - await expect(forumLink).toHaveAttribute( - 'href', - 'https://forum.freecodecamp.org' - ); + await expect( + page.getByRole('heading', { + level: 1, + name: translations.misc['email-signup'] + }) + ).toBeVisible(); + await expect( + page.getByText(translations.misc['email-blast']) + ).toBeVisible(); + await expect( + page.getByRole('link', { + name: translations.buttons['sign-up-email-list'] + }) + ).toBeVisible(); }); test("should not enable Quincy's weekly newsletter when the user clicks the sign up button", async ({ @@ -59,9 +36,7 @@ test.describe('Email sign-up page when user is not signed in', () => { }) => { await expect(page).toHaveTitle('Email Sign Up | freeCodeCamp.org'); await expect( - page.getByText( - 'freeCodeCamp is a proven path to your first software developer job.' - ) + page.getByText(translations.misc['email-blast']) ).toBeVisible(); const signupLink = page.getByRole('link', { @@ -105,25 +80,16 @@ test.describe('Email sign-up page when user is signed in', () => { }); test('should display the content correctly', async ({ page }) => { - for (const content of contents) { - await expect(page.getByText(content)).toBeVisible(); - } - - const youtubeLink = page.getByRole('link', { - name: "freeCodeCamp's YouTube channel" - }); - await expect(youtubeLink).toHaveAttribute( - 'href', - 'https://youtube.com/freecodecamp' - ); - - const forumLink = page.getByRole('link', { - name: 'the freeCodeCamp forum' - }); - await expect(forumLink).toHaveAttribute( - 'href', - 'https://forum.freecodecamp.org' - ); + await expect(page).toHaveTitle('Email Sign Up | freeCodeCamp.org'); + await expect( + page.getByText(translations.misc['email-blast']) + ).toBeVisible(); + await expect( + page.getByRole('button', { name: translations.buttons['yes-please'] }) + ).toBeVisible(); + await expect( + page.getByRole('button', { name: translations.buttons['no-thanks'] }) + ).toBeVisible(); }); test("should disable Quincy's weekly newsletter if the user clicks No", async ({ @@ -131,9 +97,7 @@ test.describe('Email sign-up page when user is signed in', () => { }) => { await expect(page).toHaveTitle('Email Sign Up | freeCodeCamp.org'); await expect( - page.getByText( - 'freeCodeCamp is a proven path to your first software developer job.' - ) + page.getByText(translations.misc['email-blast']) ).toBeVisible(); const noThanksButton = page.getByRole('button', { @@ -167,9 +131,7 @@ test.describe('Email sign-up page when user is signed in', () => { }) => { await expect(page).toHaveTitle('Email Sign Up | freeCodeCamp.org'); await expect( - page.getByText( - 'freeCodeCamp is a proven path to your first software developer job.' - ) + page.getByText(translations.misc['email-blast']) ).toBeVisible(); const signupButton = page.getByRole('button', { @@ -210,3 +172,40 @@ test.describe('Email sign-up page when user is signed in', () => { ).toHaveAttribute('aria-pressed', 'false'); }); }); + +test.describe('Email sign-up page when the user is new', () => { + test.use({ storageState: 'playwright/.auth/development-user.json' }); + + test.beforeEach(async ({ page }) => { + // It's necessary to seed with a user that has not accepted the privacy + // terms, otherwise the user will be redirected away from the email sign-up + // page. + execSync( + 'node ./tools/scripts/seed/seed-demo-user --set-false acceptedPrivacyTerms' + ); + + await page.goto('/email-sign-up'); + }); + + test.afterAll(() => { + execSync('node ./tools/scripts/seed/seed-demo-user --certified-user'); + }); + + test('should display the content correctly', async ({ page }) => { + await expect( + page.getByRole('heading', { + level: 1, + name: translations.misc['brand-new-account'] + }) + ).toBeVisible(); + await expect( + page.getByText(translations.misc['email-blast']) + ).toBeVisible(); + await expect( + page.getByRole('button', { name: translations.buttons['yes-please'] }) + ).toBeVisible(); + await expect( + page.getByRole('button', { name: translations.buttons['no-thanks'] }) + ).toBeVisible(); + }); +});