Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/reporter/src/header/header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,29 @@ $color-transition: color 150ms ease-out;
align-items: center;
flex: 1;

&.sticky-header {
position: sticky;
top: 64px; // Height of main header
z-index: 10;
background-color: $gray-1100;

&::after {
content: '';
position: absolute;
top: 100%;
left: 0;
right: 0;
height: 16px;
background: linear-gradient(
to bottom,
$gray-1100 0%,
rgba(22, 24, 39, 0.3) 100%
);
pointer-events: none;
z-index: 9;
}
}

span > span > a > svg {
margin-bottom: -2px;
margin-right: 8px;
Expand Down
5 changes: 3 additions & 2 deletions packages/reporter/src/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ export interface ReporterHeaderProps {
statsStore: StatsStore
runnablesStore: RunnablesStore
spec?: Cypress.Cypress['spec']
experimentalStudio?: boolean
}

const Header: React.FC<ReporterHeaderProps> = observer(({ appState, events = defaultEvents, statsStore, runnablesStore, spec }: ReporterHeaderProps) => {
const Header: React.FC<ReporterHeaderProps> = observer(({ appState, events = defaultEvents, statsStore, runnablesStore, spec, experimentalStudio }: ReporterHeaderProps) => {
return <header>
<div className='spec-container'>
<Tooltip placement='bottom' title={<p>{appState.isSpecsListOpen ? 'Collapse' : 'Expand'} Specs List <span className='kbd'>F</span></p>} wrapperClassName='toggle-specs-wrapper' className='cy-tooltip'>
Expand All @@ -44,7 +45,7 @@ const Header: React.FC<ReporterHeaderProps> = observer(({ appState, events = def
</Button>
</div>
</Tooltip>
{spec && <RunnableHeader spec={spec} statsStore={statsStore} runnablesStore={runnablesStore} />}
{spec && <RunnableHeader spec={spec} statsStore={statsStore} runnablesStore={runnablesStore} experimentalStudio={experimentalStudio} />}
</div>
<div className='statsAndControls'>
<Stats stats={statsStore} />
Expand Down
20 changes: 19 additions & 1 deletion packages/reporter/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ import TestingPreferences from './preferences/testing-preferences'
import type { MobxRunnerStore } from '@packages/app/src/store/mobx-runner-store'
import { StudioTestHeader } from './studio/StudioTestHeader'

// Import the config function to access experimental features
function getRunnerConfigFromWindow () {
try {
// Use the same approach as the app's reporter.ts
if (typeof window !== 'undefined' && window.__CYPRESS_CONFIG__?.base64Config) {
const { decodeBase64Unicode } = require('@packages/frontend-shared/src/utils/base64')
return JSON.parse(decodeBase64Unicode(window.__CYPRESS_CONFIG__.base64Config)) as Cypress.Config
}
} catch (e) {
// Fallback to empty config if parsing fails
console.warn('Failed to parse Cypress config:', e)
}
return {} as Cypress.Config
}

function usePrevious (value) {
const ref = useRef()

Expand Down Expand Up @@ -51,7 +66,10 @@ export interface SingleReporterProps extends BaseReporterProps {
}

// In React Class components (now deprecated), we used to use appState as a default prop. Now since defaultProps are not supported in functional components, we can use ES6 default params to accomplish the same thing
const Reporter: React.FC<SingleReporterProps> = observer(({ appState = appStateDefault, runner, className, error, runMode = 'single', studioEnabled, autoScrollingEnabled, isSpecsListOpen, resetStatsOnSpecChange, renderReporterHeader = (props: ReporterHeaderProps) => <Header {...props} />, runnerStore }) => {
const Reporter: React.FC<SingleReporterProps> = observer(({ appState = appStateDefault, runner, className, error, runMode = 'single', studioEnabled, autoScrollingEnabled, isSpecsListOpen, resetStatsOnSpecChange, renderReporterHeader = (props: ReporterHeaderProps) => {
const config = getRunnerConfigFromWindow()
return <Header {...props} experimentalStudio={config.experimentalStudio} />
}, runnerStore }) => {
const previousSpecRunId = usePrevious(runnerStore.specRunId)
const [isMounted, setIsMounted] = useState(false)
const [isInitialized, setIsInitialized] = useState(false)
Expand Down
15 changes: 13 additions & 2 deletions packages/reporter/src/runnables/runnable-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,34 @@ import { DebugDismiss } from '../header/DebugDismiss'
import { Duration } from '../duration/duration'
import { SpecFileName } from '../shared/SpecFileName'

const renderRunnableHeader = (children: ReactElement) => <div className="runnable-header" data-cy="runnable-header">{children}</div>
const renderRunnableHeader = (children: ReactElement, enableStickyHeader?: boolean) => (
<div
className={`runnable-header${enableStickyHeader ? ' sticky-header' : ''}`}
data-cy="runnable-header"
>
{children}
</div>
)

interface RunnableHeaderProps {
spec: Cypress.Cypress['spec']
statsStore: StatsStore
runnablesStore: RunnablesStore
experimentalStudio?: boolean
}

const RunnableHeader: React.FC<RunnableHeaderProps> = observer(({ spec, statsStore, runnablesStore }) => {
const RunnableHeader: React.FC<RunnableHeaderProps> = observer(({ spec, statsStore, runnablesStore, experimentalStudio }) => {
if (spec.relative === '__all') {
if (spec.specFilter) {
return renderRunnableHeader(
<span><span>Specs matching "{spec.specFilter}"</span></span>,
experimentalStudio,
)
}

return renderRunnableHeader(
<span><span>All Specs</span></span>,
experimentalStudio,
)
}

Expand All @@ -34,6 +44,7 @@ const RunnableHeader: React.FC<RunnableHeaderProps> = observer(({ spec, statsSto
{runnablesStore.testFilter && runnablesStore.totalTests > 0 && <DebugDismiss matched={runnablesStore.totalTests} total={runnablesStore.totalUnfilteredTests} />}
<Duration duration={statsStore.duration} />
</>,
experimentalStudio,
)
})

Expand Down
Loading