From 733aa369f03a03bd30dfb0c56190fed5d6d667f3 Mon Sep 17 00:00:00 2001 From: Calvin Yau Date: Mon, 5 May 2025 15:59:50 -0700 Subject: [PATCH 1/4] feat(codecov): Add onboarding radio selector for GHA or CLI --- static/app/routes.tsx | 4 +- .../{ => onboarding}/onboarding.spec.tsx | 2 +- .../codecov/tests/onboarding/onboarding.tsx | 71 +++++++++++++++++++ .../tests/onboarding/onboardingStep.tsx | 27 +++++++ static/app/views/codecov/tests/tests.tsx | 2 + 5 files changed, 104 insertions(+), 2 deletions(-) rename static/app/views/codecov/tests/{ => onboarding}/onboarding.spec.tsx (95%) create mode 100644 static/app/views/codecov/tests/onboarding/onboarding.tsx create mode 100644 static/app/views/codecov/tests/onboarding/onboardingStep.tsx diff --git a/static/app/routes.tsx b/static/app/routes.tsx index 8511087af5e12e..62d36430e31389 100644 --- a/static/app/routes.tsx +++ b/static/app/routes.tsx @@ -2022,7 +2022,9 @@ function buildRoutes() { {/* Render tests onboarding without any layout wrapping */} import('sentry/views/codecov/tests/onboarding'))} + component={make( + () => import('sentry/views/codecov/tests/onboarding/onboarding') + )} /> diff --git a/static/app/views/codecov/tests/onboarding.spec.tsx b/static/app/views/codecov/tests/onboarding/onboarding.spec.tsx similarity index 95% rename from static/app/views/codecov/tests/onboarding.spec.tsx rename to static/app/views/codecov/tests/onboarding/onboarding.spec.tsx index 7d2591bae88d49..be1a5033156be9 100644 --- a/static/app/views/codecov/tests/onboarding.spec.tsx +++ b/static/app/views/codecov/tests/onboarding/onboarding.spec.tsx @@ -2,7 +2,7 @@ import {OrganizationFixture} from 'sentry-fixture/organization'; import {render, screen} from 'sentry-test/reactTestingLibrary'; -import TestAnalyticsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; +import TestAnalyticsOnboardingPage from 'sentry/views/codecov/tests/onboarding/onboarding'; const COVERAGE_FEATURE = 'codecov-ui'; diff --git a/static/app/views/codecov/tests/onboarding/onboarding.tsx b/static/app/views/codecov/tests/onboarding/onboarding.tsx new file mode 100644 index 00000000000000..8cbb91d1631042 --- /dev/null +++ b/static/app/views/codecov/tests/onboarding/onboarding.tsx @@ -0,0 +1,71 @@ +import {useState} from 'react'; +import styled from '@emotion/styled'; + +import RadioGroup from 'sentry/components/forms/controls/radioGroup'; +import {t} from 'sentry/locale'; +import {space} from 'sentry/styles/space'; + +type SetupOption = 'githubAction' | 'cli'; + +export default function TestsOnboardingPage() { + const [selectedOption, setSelectedOption] = useState('githubAction'); + + return ( + +

Test Analytics Onboarding

+ + + {t('Get Started with Test Analytics')} + + {t( + 'Test Analytics offers data on test run times, failure rates, and identifies flaky tests to help decrease the risk of deployment failures and make it easier to ship new features quickly.' + )} + + + Select a setup option + setSelectedOption(opt as SetupOption)} + choices={[ + ['githubAction', t('Use GitHub Actions to run my CI')], + ['cli', t("Use Sentry Prevent's CLI to upload testing reports")], + ]} + /> + +
+ ); +} + +const LayoutGap = styled('div')` + display: grid; + gap: ${space(2)}; +`; + +const OnboardingContainer = styled('div')` + padding: ${space(1.5)} ${space(4)}; + border: 1px solid ${p => p.theme.border}; + border-radius: ${p => p.theme.borderRadius}; +`; + +const IntroContainer = styled('div')` + border-bottom: 1px solid ${p => p.theme.border}; + padding-bottom: ${space(3)}; +`; + +const GetStartedHeader = styled('h2')` + font-size: 1.625rem; + color: ${p => p.theme.tokens.content.primary}; + line-height: 40px; +`; + +const TAValueText = styled('p')` + font-size: ${p => p.theme.fontSizeLarge}; + color: ${p => p.theme.tokens.content.primary}; +`; + +const SelectOptionHeader = styled('h5')` + font-size: ${p => p.theme.fontSizeExtraLarge}; + color: ${p => p.theme.tokens.content.primary}; + margin-top: ${space(3)}; +`; diff --git a/static/app/views/codecov/tests/onboarding/onboardingStep.tsx b/static/app/views/codecov/tests/onboarding/onboardingStep.tsx new file mode 100644 index 00000000000000..d34162c937adb5 --- /dev/null +++ b/static/app/views/codecov/tests/onboarding/onboardingStep.tsx @@ -0,0 +1,27 @@ +import styled from '@emotion/styled'; + +import {space} from 'sentry/styles/space'; + +const Container = styled('div')` + display: flex; + flex-direction: column; + gap: ${space(1)}; + border: 1px solid ${p => p.theme.border}; + border-radius: ${p => p.theme.borderRadius}; + padding: ${space(2)} ${space(3)}; +`; + +const Header = styled('h5')` + font-size: ${p => p.theme.fontSizeExtraLarge}; + color: ${p => p.theme.gray300}; +`; + +const Content = styled('div')` + /* flex-grow: 1; */ +`; + +export const OnboardingStep = { + Container, + Header, + Content, +}; diff --git a/static/app/views/codecov/tests/tests.tsx b/static/app/views/codecov/tests/tests.tsx index 17a681b73669d0..1864211513fd47 100644 --- a/static/app/views/codecov/tests/tests.tsx +++ b/static/app/views/codecov/tests/tests.tsx @@ -4,6 +4,7 @@ import {DatePicker} from 'sentry/components/codecov/datePicker/datePicker'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import {space} from 'sentry/styles/space'; +import TestsOnboardingPage from 'sentry/views/codecov/tests/onboarding/onboarding'; import {Summaries} from 'sentry/views/codecov/tests/summaries/summaries'; const DEFAULT_CODECOV_DATETIME_SELECTION = { @@ -26,6 +27,7 @@ export default function TestsPage() { {/* TODO: Conditionally show these if the branch we're in is the main branch */} + ); } From 163a5f49a0459f209ed3f49fd03fdc372b4204c5 Mon Sep 17 00:00:00 2001 From: Calvin Yau Date: Mon, 12 May 2025 11:33:09 -0700 Subject: [PATCH 2/4] feat(codecov): Update url when changing option radio --- static/app/routes.tsx | 4 +- .../{onboarding => }/onboarding.spec.tsx | 2 +- static/app/views/codecov/tests/onboarding.tsx | 65 ++++++++++++++++- .../codecov/tests/onboarding/onboarding.tsx | 71 ------------------- .../tests/{onboarding => }/onboardingStep.tsx | 0 static/app/views/codecov/tests/tests.tsx | 2 +- 6 files changed, 66 insertions(+), 78 deletions(-) rename static/app/views/codecov/tests/{onboarding => }/onboarding.spec.tsx (95%) delete mode 100644 static/app/views/codecov/tests/onboarding/onboarding.tsx rename static/app/views/codecov/tests/{onboarding => }/onboardingStep.tsx (100%) diff --git a/static/app/routes.tsx b/static/app/routes.tsx index 62d36430e31389..8511087af5e12e 100644 --- a/static/app/routes.tsx +++ b/static/app/routes.tsx @@ -2022,9 +2022,7 @@ function buildRoutes() { {/* Render tests onboarding without any layout wrapping */} import('sentry/views/codecov/tests/onboarding/onboarding') - )} + component={make(() => import('sentry/views/codecov/tests/onboarding'))} /> diff --git a/static/app/views/codecov/tests/onboarding/onboarding.spec.tsx b/static/app/views/codecov/tests/onboarding.spec.tsx similarity index 95% rename from static/app/views/codecov/tests/onboarding/onboarding.spec.tsx rename to static/app/views/codecov/tests/onboarding.spec.tsx index be1a5033156be9..7d2591bae88d49 100644 --- a/static/app/views/codecov/tests/onboarding/onboarding.spec.tsx +++ b/static/app/views/codecov/tests/onboarding.spec.tsx @@ -2,7 +2,7 @@ import {OrganizationFixture} from 'sentry-fixture/organization'; import {render, screen} from 'sentry-test/reactTestingLibrary'; -import TestAnalyticsOnboardingPage from 'sentry/views/codecov/tests/onboarding/onboarding'; +import TestAnalyticsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; const COVERAGE_FEATURE = 'codecov-ui'; diff --git a/static/app/views/codecov/tests/onboarding.tsx b/static/app/views/codecov/tests/onboarding.tsx index 96665760de77d5..496343dad8d624 100644 --- a/static/app/views/codecov/tests/onboarding.tsx +++ b/static/app/views/codecov/tests/onboarding.tsx @@ -1,13 +1,46 @@ +import {useCallback} from 'react'; +import {useSearchParams} from 'react-router-dom'; import styled from '@emotion/styled'; +import RadioGroup from 'sentry/components/forms/controls/radioGroup'; +import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; -import TestPreOnboardingPage from 'sentry/views/codecov/tests/preOnboarding'; + +type SetupOption = 'githubAction' | 'cli'; export default function TestsOnboardingPage() { + const [searchParams, setSearchParams] = useSearchParams(); + const opt = searchParams.get('opt'); + const handleRadioChange = useCallback( + (newOption: SetupOption) => { + setSearchParams({opt: newOption}); + }, + [setSearchParams] + ); + return (

Test Analytics Onboarding

- + + + {t('Get Started with Test Analytics')} + + {t( + 'Test Analytics offers data on test run times, failure rates, and identifies flaky tests to help decrease the risk of deployment failures and make it easier to ship new features quickly.' + )} + + + Select a setup option + +
); } @@ -16,3 +49,31 @@ const LayoutGap = styled('div')` display: grid; gap: ${space(2)}; `; + +const OnboardingContainer = styled('div')` + padding: ${space(1.5)} ${space(4)}; + border: 1px solid ${p => p.theme.border}; + border-radius: ${p => p.theme.borderRadius}; +`; + +const IntroContainer = styled('div')` + border-bottom: 1px solid ${p => p.theme.border}; + padding-bottom: ${space(3)}; +`; + +const GetStartedHeader = styled('h2')` + font-size: 1.625rem; + color: ${p => p.theme.tokens.content.primary}; + line-height: 40px; +`; + +const TAValueText = styled('p')` + font-size: ${p => p.theme.fontSizeLarge}; + color: ${p => p.theme.tokens.content.primary}; +`; + +const SelectOptionHeader = styled('h5')` + font-size: ${p => p.theme.fontSizeExtraLarge}; + color: ${p => p.theme.tokens.content.primary}; + margin-top: ${space(3)}; +`; diff --git a/static/app/views/codecov/tests/onboarding/onboarding.tsx b/static/app/views/codecov/tests/onboarding/onboarding.tsx deleted file mode 100644 index 8cbb91d1631042..00000000000000 --- a/static/app/views/codecov/tests/onboarding/onboarding.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import {useState} from 'react'; -import styled from '@emotion/styled'; - -import RadioGroup from 'sentry/components/forms/controls/radioGroup'; -import {t} from 'sentry/locale'; -import {space} from 'sentry/styles/space'; - -type SetupOption = 'githubAction' | 'cli'; - -export default function TestsOnboardingPage() { - const [selectedOption, setSelectedOption] = useState('githubAction'); - - return ( - -

Test Analytics Onboarding

- - - {t('Get Started with Test Analytics')} - - {t( - 'Test Analytics offers data on test run times, failure rates, and identifies flaky tests to help decrease the risk of deployment failures and make it easier to ship new features quickly.' - )} - - - Select a setup option - setSelectedOption(opt as SetupOption)} - choices={[ - ['githubAction', t('Use GitHub Actions to run my CI')], - ['cli', t("Use Sentry Prevent's CLI to upload testing reports")], - ]} - /> - -
- ); -} - -const LayoutGap = styled('div')` - display: grid; - gap: ${space(2)}; -`; - -const OnboardingContainer = styled('div')` - padding: ${space(1.5)} ${space(4)}; - border: 1px solid ${p => p.theme.border}; - border-radius: ${p => p.theme.borderRadius}; -`; - -const IntroContainer = styled('div')` - border-bottom: 1px solid ${p => p.theme.border}; - padding-bottom: ${space(3)}; -`; - -const GetStartedHeader = styled('h2')` - font-size: 1.625rem; - color: ${p => p.theme.tokens.content.primary}; - line-height: 40px; -`; - -const TAValueText = styled('p')` - font-size: ${p => p.theme.fontSizeLarge}; - color: ${p => p.theme.tokens.content.primary}; -`; - -const SelectOptionHeader = styled('h5')` - font-size: ${p => p.theme.fontSizeExtraLarge}; - color: ${p => p.theme.tokens.content.primary}; - margin-top: ${space(3)}; -`; diff --git a/static/app/views/codecov/tests/onboarding/onboardingStep.tsx b/static/app/views/codecov/tests/onboardingStep.tsx similarity index 100% rename from static/app/views/codecov/tests/onboarding/onboardingStep.tsx rename to static/app/views/codecov/tests/onboardingStep.tsx diff --git a/static/app/views/codecov/tests/tests.tsx b/static/app/views/codecov/tests/tests.tsx index 1864211513fd47..7e41be1ed2300e 100644 --- a/static/app/views/codecov/tests/tests.tsx +++ b/static/app/views/codecov/tests/tests.tsx @@ -4,7 +4,7 @@ import {DatePicker} from 'sentry/components/codecov/datePicker/datePicker'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import {space} from 'sentry/styles/space'; -import TestsOnboardingPage from 'sentry/views/codecov/tests/onboarding/onboarding'; +import TestsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; import {Summaries} from 'sentry/views/codecov/tests/summaries/summaries'; const DEFAULT_CODECOV_DATETIME_SELECTION = { From afe4b07138f598b3015da6ce8d97c04922488345 Mon Sep 17 00:00:00 2001 From: Calvin Yau Date: Tue, 13 May 2025 10:50:21 -0700 Subject: [PATCH 3/4] test(codecov): Test radio button --- .../views/codecov/tests/onboarding.spec.tsx | 83 ++++++++++++++++--- .../views/codecov/tests/onboardingStep.tsx | 27 ------ static/app/views/codecov/tests/tests.tsx | 2 - 3 files changed, 73 insertions(+), 39 deletions(-) delete mode 100644 static/app/views/codecov/tests/onboardingStep.tsx diff --git a/static/app/views/codecov/tests/onboarding.spec.tsx b/static/app/views/codecov/tests/onboarding.spec.tsx index 7d2591bae88d49..be32847d2ff7f7 100644 --- a/static/app/views/codecov/tests/onboarding.spec.tsx +++ b/static/app/views/codecov/tests/onboarding.spec.tsx @@ -1,18 +1,81 @@ -import {OrganizationFixture} from 'sentry-fixture/organization'; +import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; -import {render, screen} from 'sentry-test/reactTestingLibrary'; +import TestsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; -import TestAnalyticsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; +describe('TestsOnboardingPage', () => { + it('renders with GitHub Actions selected by default', () => { + render(, { + initialRouterConfig: { + location: { + pathname: '/codecov/tests/new', + query: {opt: ''}, + }, + }, + }); + + const githubRadio = screen.getByLabelText('Use GitHub Actions to run my CI'); + expect(githubRadio).toBeChecked(); + + const cliRadio = screen.getByLabelText( + "Use Sentry Prevent's CLI to upload testing reports" + ); + expect(cliRadio).not.toBeChecked(); + }); + + it('renders with CLI selected when opt=cli in URL', () => { + render(, { + initialRouterConfig: { + location: { + pathname: '/codecov/tests/new', + query: {opt: 'cli'}, + }, + }, + }); + + const cliRadio = screen.getByLabelText( + "Use Sentry Prevent's CLI to upload testing reports" + ); + expect(cliRadio).toBeChecked(); + + const githubRadio = screen.getByLabelText('Use GitHub Actions to run my CI'); + expect(githubRadio).not.toBeChecked(); + }); + + it('updates URL when GitHub Actions option is selected', async () => { + const {router} = render(, { + initialRouterConfig: { + location: { + pathname: '/codecov/tests/new', + query: {opt: 'cli'}, + }, + }, + }); + + const githubRadio = screen.getByLabelText('Use GitHub Actions to run my CI'); + expect(githubRadio).not.toBeChecked(); -const COVERAGE_FEATURE = 'codecov-ui'; + await userEvent.click(githubRadio); -describe('TestAnalyticsOnboardingPage', () => { - it('renders the placeholder content', () => { - render(, { - organization: OrganizationFixture({features: [COVERAGE_FEATURE]}), + expect(router.location.search).toBe('?opt=githubAction'); + }); + + it('updates URL when CLI option is selected', async () => { + const {router} = render(, { + initialRouterConfig: { + location: { + pathname: '/codecov/tests/new', + query: {opt: ''}, + }, + }, }); - const testContent = screen.getByText('Test Analytics Onboarding'); - expect(testContent).toBeInTheDocument(); + const cliRadio = screen.getByLabelText( + "Use Sentry Prevent's CLI to upload testing reports" + ); + expect(cliRadio).not.toBeChecked(); + + await userEvent.click(cliRadio); + + expect(router.location.search).toBe('?opt=cli'); }); }); diff --git a/static/app/views/codecov/tests/onboardingStep.tsx b/static/app/views/codecov/tests/onboardingStep.tsx deleted file mode 100644 index d34162c937adb5..00000000000000 --- a/static/app/views/codecov/tests/onboardingStep.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import styled from '@emotion/styled'; - -import {space} from 'sentry/styles/space'; - -const Container = styled('div')` - display: flex; - flex-direction: column; - gap: ${space(1)}; - border: 1px solid ${p => p.theme.border}; - border-radius: ${p => p.theme.borderRadius}; - padding: ${space(2)} ${space(3)}; -`; - -const Header = styled('h5')` - font-size: ${p => p.theme.fontSizeExtraLarge}; - color: ${p => p.theme.gray300}; -`; - -const Content = styled('div')` - /* flex-grow: 1; */ -`; - -export const OnboardingStep = { - Container, - Header, - Content, -}; diff --git a/static/app/views/codecov/tests/tests.tsx b/static/app/views/codecov/tests/tests.tsx index 7e41be1ed2300e..17a681b73669d0 100644 --- a/static/app/views/codecov/tests/tests.tsx +++ b/static/app/views/codecov/tests/tests.tsx @@ -4,7 +4,6 @@ import {DatePicker} from 'sentry/components/codecov/datePicker/datePicker'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import {space} from 'sentry/styles/space'; -import TestsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; import {Summaries} from 'sentry/views/codecov/tests/summaries/summaries'; const DEFAULT_CODECOV_DATETIME_SELECTION = { @@ -27,7 +26,6 @@ export default function TestsPage() { {/* TODO: Conditionally show these if the branch we're in is the main branch */} - ); } From e8695d6889c87b91b3f65d9448b5ed5ea2c00b7e Mon Sep 17 00:00:00 2001 From: Calvin Yau Date: Thu, 15 May 2025 15:31:41 -0700 Subject: [PATCH 4/4] test(codecov): Add empty opt param test --- .../views/codecov/tests/onboarding.spec.tsx | 21 ++++++++++++++++++- static/app/views/codecov/tests/onboarding.tsx | 3 ++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/static/app/views/codecov/tests/onboarding.spec.tsx b/static/app/views/codecov/tests/onboarding.spec.tsx index be32847d2ff7f7..8b1b6afeaa6292 100644 --- a/static/app/views/codecov/tests/onboarding.spec.tsx +++ b/static/app/views/codecov/tests/onboarding.spec.tsx @@ -3,7 +3,26 @@ import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; import TestsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; describe('TestsOnboardingPage', () => { - it('renders with GitHub Actions selected by default', () => { + it('renders with GitHub Actions selected by default if no query param is provided', () => { + render(, { + initialRouterConfig: { + location: { + pathname: '/codecov/tests/new', + query: {}, + }, + }, + }); + + const githubRadio = screen.getByLabelText('Use GitHub Actions to run my CI'); + expect(githubRadio).toBeChecked(); + + const cliRadio = screen.getByLabelText( + "Use Sentry Prevent's CLI to upload testing reports" + ); + expect(cliRadio).not.toBeChecked(); + }); + + it('renders with GitHub Actions selected by default if empty opt query param is provided', () => { render(, { initialRouterConfig: { location: { diff --git a/static/app/views/codecov/tests/onboarding.tsx b/static/app/views/codecov/tests/onboarding.tsx index 496343dad8d624..959c248f5cc606 100644 --- a/static/app/views/codecov/tests/onboarding.tsx +++ b/static/app/views/codecov/tests/onboarding.tsx @@ -11,6 +11,7 @@ type SetupOption = 'githubAction' | 'cli'; export default function TestsOnboardingPage() { const [searchParams, setSearchParams] = useSearchParams(); const opt = searchParams.get('opt'); + const handleRadioChange = useCallback( (newOption: SetupOption) => { setSearchParams({opt: newOption}); @@ -30,7 +31,7 @@ export default function TestsOnboardingPage() { )} - Select a setup option + {t('Select a setup option')}