diff --git a/static/app/views/codecov/tests/onboarding.tsx b/static/app/views/codecov/tests/onboarding.tsx index 959c248f5cc606..60186d6c9aa043 100644 --- a/static/app/views/codecov/tests/onboarding.tsx +++ b/static/app/views/codecov/tests/onboarding.tsx @@ -5,6 +5,8 @@ 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 {OutputCoverageFile} from 'sentry/views/codecov/tests/onboardingSteps/outputCoverageFile'; +import TestPreOnboardingPage from 'sentry/views/codecov/tests/preOnboarding'; type SetupOption = 'githubAction' | 'cli'; @@ -22,6 +24,7 @@ export default function TestsOnboardingPage() { return (

Test Analytics Onboarding

+ {t('Get Started with Test Analytics')} @@ -41,6 +44,9 @@ export default function TestsOnboardingPage() { ['cli', t("Use Sentry Prevent's CLI to upload testing reports")], ]} /> + + +
); @@ -78,3 +84,7 @@ const SelectOptionHeader = styled('h5')` color: ${p => p.theme.tokens.content.primary}; margin-top: ${space(3)}; `; + +const StepsContainer = styled('div')` + padding: ${space(3)} ${space(4)}; +`; diff --git a/static/app/views/codecov/tests/onboardingSteps/onboardingStep.tsx b/static/app/views/codecov/tests/onboardingSteps/onboardingStep.tsx new file mode 100644 index 00000000000000..c78eb17000349b --- /dev/null +++ b/static/app/views/codecov/tests/onboardingSteps/onboardingStep.tsx @@ -0,0 +1,28 @@ +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('h3')` + font-size: ${p => p.theme.fontSizeExtraLarge}; + color: ${p => p.theme.gray300}; + margin-bottom: 0; +`; + +const Content = styled('div')` + /* flex-grow: 1; */ +`; + +export const OnboardingStep = { + Container, + Header, + Content, +}; diff --git a/static/app/views/codecov/tests/onboardingSteps/outputCoverageFile.tsx b/static/app/views/codecov/tests/onboardingSteps/outputCoverageFile.tsx new file mode 100644 index 00000000000000..b11e438e72c27b --- /dev/null +++ b/static/app/views/codecov/tests/onboardingSteps/outputCoverageFile.tsx @@ -0,0 +1,93 @@ +import {Fragment, useState} from 'react'; +import {Link} from 'react-router-dom'; +import styled from '@emotion/styled'; + +import {CodeSnippet} from 'sentry/components/codeSnippet'; +import {Select} from 'sentry/components/core/select'; +import {t, tct} from 'sentry/locale'; +import {space} from 'sentry/styles/space'; +import {OnboardingStep} from 'sentry/views/codecov/tests/onboardingSteps/onboardingStep'; + +interface OutputCoverageFileProps { + step: string; +} + +type Frameworks = 'jest' | 'vitest' | 'pytest' | 'phpunit'; + +const INSTALL_REQUIREMENTS_SNIPPETS: Record = { + jest: `pytest --cov --junitxml=junit.xml -o junit_family=legacy`, + vitest: `vitest --reporter=junit --outputFile=test-report.junit.xml`, + pytest: `npm i --save-dev jest-junit`, + phpunit: `./vendor/bin/phpunit --log-junit junit.xml`, +}; + +const GENERATE_FILE_SNIPPETS: Record = { + jest: '', + vitest: '', + pytest: `JEST_JUNIT_CLASSNAME="{filepath}" jest --reporters=jest-junit`, + phpunit: '', +}; + +export function OutputCoverageFile({step}: OutputCoverageFileProps) { + const headerText = tct('Step [step]: Output a JUnit XML file in your CI', { + step, + }); + const [selectedFramework, setSelectedFramework] = useState('jest'); + + return ( + + {headerText} + +

+ {tct( + "Select your language below to generate your testing reports. If your language isn't listed, visit [supported] for your testing framework. Currently, Sentry supports JUnit XML format only.", + { + supported: ( + // TODO: the new version of this link is still TBD + + {t('supported languages')} + + ), + } + )} +

+ setSelectedFramework(option.value)} + /> + + {t('Install requirements in your terminal:')} + + + {INSTALL_REQUIREMENTS_SNIPPETS[selectedFramework]} + + {selectedFramework === 'pytest' ? ( + + + {t('Generate a JUnit XML file that contains the results of your test run.')} + + + {GENERATE_FILE_SNIPPETS.pytest} + + + ) : null} +
+
+ ); +} + +const StyledSelectControl = styled(Select)` + width: 110px; + margin-bottom: ${space(1.5)}; +`; + +const StyledInstruction = styled('p')` + margin: ${space(1.5)} 0; +`; diff --git a/static/app/views/codecov/tests/tests.tsx b/static/app/views/codecov/tests/tests.tsx index a32b07038ae1ab..7f1a0d2a63ecd1 100644 --- a/static/app/views/codecov/tests/tests.tsx +++ b/static/app/views/codecov/tests/tests.tsx @@ -8,6 +8,7 @@ import PageFiltersContainer from 'sentry/components/organizations/pageFilters/co import {space} from 'sentry/styles/space'; import {decodeSorts} from 'sentry/utils/queryString'; import {useLocation} from 'sentry/utils/useLocation'; +import TestsOnboardingPage from 'sentry/views/codecov/tests/onboarding'; import {DEFAULT_SORT} from 'sentry/views/codecov/tests/settings'; import {Summaries} from 'sentry/views/codecov/tests/summaries/summaries'; import type {ValidSort} from 'sentry/views/codecov/tests/testAnalyticsTable/testAnalyticsTable'; @@ -81,6 +82,7 @@ export default function TestsPage() { {/* TODO: Conditionally show these if the branch we're in is the main branch */} + ); }