diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 64c396650a3..7cab9e837d5 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -6,6 +6,7 @@ _Released 10/7/2025 (PENDING)_ **Features:** - Cypress Studio is now available by default. You no longer have to set the `experimentalStudio` flag. Addresses [#30997](https://github.com/cypress-io/cypress/issues/30997). Addressed in [#32571](https://github.com/cypress-io/cypress/pull/32571). +- An option is now available to 'Hide HTTP Requests' in the Cypress Command Log. This can be found in the new dropdown menu at the top of the Command Log. Addresses [#7362](https://github.com/cypress-io/cypress/issues/7362). Addressed in [#32658](https://github.com/cypress-io/cypress/pull/32658). - Added the `--posix-exit-codes` flag for the `run` command. When this flag is passed, Cypress will exit with 1 if any tests fail, rather than the number of failed tests. Addresses [#32605](https://github.com/cypress-io/cypress/issues/32605) and [#24695](https://github.com/cypress-io/cypress/issues/24695). Addressed in [#32609](https://github.com/cypress-io/cypress/pull/32609). - `cy.prompt` is now a reserved Cypress command, currently gated behind a feature flag that requires an invite from Cypress. This means any custom commands named 'prompt' will no longer work. Stay tuned for updates on when this feature will become more widely available. Addresses [#31826](https://github.com/cypress-io/cypress/issues/31826). @@ -17,7 +18,7 @@ _Released 10/7/2025 (PENDING)_ **Misc:** -- Added a dropdown menu in the Command Log that includes actions like Open in IDE and Add New Test in Studio, along with test preferences such as Auto-Scroll. Addresses [#32556](https://github.com/cypress-io/cypress/issues/32556) and [#32558](https://github.com/cypress-io/cypress/issues/32558). Addressed in [#32611](https://github.com/cypress-io/cypress/pull/32611). +- Added a dropdown menu in the Command Log that includes actions like Open in IDE and Add New Test in Studio, along with test preferences such as Auto-Scroll and Hide HTTP Requests. Addresses [#32556](https://github.com/cypress-io/cypress/issues/32556) and [#32558](https://github.com/cypress-io/cypress/issues/32558). Addressed in [#32611](https://github.com/cypress-io/cypress/pull/32611). - Updated the Studio test editing header to include a Back button. This change ensures the Specs button remains functional for expanding or collapsing the specs panel. Addresses [#32556](https://github.com/cypress-io/cypress/issues/32556) and [#32558](https://github.com/cypress-io/cypress/issues/32558). Addressed in [#32611](https://github.com/cypress-io/cypress/pull/32611). - Fixed the Studio panel resizing when dragging. Addressed in [#32584](https://github.com/cypress-io/cypress/pull/32584). - The Next button now maintains consistent visibility during stepping sessions when using `cy.pause`, staying visible but disabled when no immediate next command is available, providing clear visual feedback to users about stepping state. Addresses [#32476](https://github.com/cypress-io/cypress/issues/32476). Addressed in [#32536](https://github.com/cypress-io/cypress/pull/32536). diff --git a/packages/app/src/navigation/SidebarNavigation.vue b/packages/app/src/navigation/SidebarNavigation.vue index af882f6fae9..31074b777cc 100644 --- a/packages/app/src/navigation/SidebarNavigation.vue +++ b/packages/app/src/navigation/SidebarNavigation.vue @@ -121,6 +121,7 @@ fragment SidebarNavigation_Settings on Query { isSideNavigationOpen isSpecsListOpen autoScrollingEnabled + showFetchRequests reporterWidth specListWidth } diff --git a/packages/app/src/runner/SpecRunnerOpenMode.vue b/packages/app/src/runner/SpecRunnerOpenMode.vue index 61f63c097a8..bfa409acf04 100644 --- a/packages/app/src/runner/SpecRunnerOpenMode.vue +++ b/packages/app/src/runner/SpecRunnerOpenMode.vue @@ -176,6 +176,7 @@ fragment SpecRunner_Preferences on Query { isSideNavigationOpen isSpecsListOpen autoScrollingEnabled + showFetchRequests reporterWidth specListWidth studioWidth @@ -355,6 +356,8 @@ onMounted(() => { preferences.update('autoScrollingEnabled', props.gql.localSettings.preferences.autoScrollingEnabled ?? true) +preferences.update('showFetchRequests', props.gql.localSettings.preferences.showFetchRequests ?? true) + // if the CYPRESS_NO_COMMAND_LOG environment variable is set, // don't use the widths or the open status of specs list from GraphQL if (!hideCommandLog) { @@ -437,6 +440,7 @@ onMounted(() => { eventManager.on('save:app:state', (state) => { preferences.update('isSpecsListOpen', state.isSpecsListOpen) preferences.update('autoScrollingEnabled', state.autoScrollingEnabled) + preferences.update('showFetchRequests', state.showFetchRequests) }) }) diff --git a/packages/app/src/runner/event-manager.ts b/packages/app/src/runner/event-manager.ts index 4bddeb5e828..ba16112d7c5 100644 --- a/packages/app/src/runner/event-manager.ts +++ b/packages/app/src/runner/event-manager.ts @@ -883,6 +883,7 @@ export class EventManager { numPending: runState.pending, autoScrollingEnabled: runState.autoScrollingEnabled, isSpecsListOpen: runState.isSpecsListOpen, + showFetchRequests: runState.showFetchRequests, scrollTop: runState.scrollTop, studioActive: hasActiveStudio, studioSingleTestActive, diff --git a/packages/app/src/runner/reporter.ts b/packages/app/src/runner/reporter.ts index 70e7dc5bcd6..644078914a8 100644 --- a/packages/app/src/runner/reporter.ts +++ b/packages/app/src/runner/reporter.ts @@ -47,6 +47,7 @@ function renderReporter ( runner: eventManager.reporterBus, autoScrollingEnabled: runnerUiStore.autoScrollingEnabled, isSpecsListOpen: runnerUiStore.isSpecsListOpen, + showFetchRequests: runnerUiStore.showFetchRequests, error: null, resetStatsOnSpecChange: true, // Studio can only be enabled for e2e testing diff --git a/packages/app/src/store/runner-ui-store.ts b/packages/app/src/store/runner-ui-store.ts index c471d7dfdac..cc21cff4108 100644 --- a/packages/app/src/store/runner-ui-store.ts +++ b/packages/app/src/store/runner-ui-store.ts @@ -22,6 +22,7 @@ export interface RunnerUiState { showChooseExternalEditorModal: boolean autoScrollingEnabled: boolean isSpecsListOpen: boolean + showFetchRequests: boolean specListWidth: number reporterWidth: number studioWidth: number @@ -39,6 +40,7 @@ export const useRunnerUiStore = defineStore({ showChooseExternalEditorModal: false, autoScrollingEnabled: true, isSpecsListOpen: false, + showFetchRequests: true, specListWidth: runnerConstants.defaultSpecListWidth, reporterWidth: runnerConstants.defaultReporterWidth, studioWidth: runnerConstants.defaultStudioWidth, diff --git a/packages/data-context/graphql/schemaTypes/objectTypes/gql-LocalSettings.ts b/packages/data-context/graphql/schemaTypes/objectTypes/gql-LocalSettings.ts index 688e53200ba..276ee544089 100644 --- a/packages/data-context/graphql/schemaTypes/objectTypes/gql-LocalSettings.ts +++ b/packages/data-context/graphql/schemaTypes/objectTypes/gql-LocalSettings.ts @@ -8,6 +8,7 @@ export const LocalSettingsPreferences = objectType({ t.boolean('autoScrollingEnabled') t.string('preferredEditorBinary') t.boolean('isSpecsListOpen') + t.boolean('showFetchRequests') t.int('reporterWidth') t.int('specListWidth') t.int('studioWidth') diff --git a/packages/data-context/schemas/schema.graphql b/packages/data-context/schemas/schema.graphql index 8ab8da2ecc9..10f14f3ccf9 100644 --- a/packages/data-context/schemas/schema.graphql +++ b/packages/data-context/schemas/schema.graphql @@ -1421,6 +1421,7 @@ type LocalSettingsPreferences { Determine if the browser should launch when the browser flag is passed alone """ shouldLaunchBrowserFromOpenBrowser: Boolean + showFetchRequests: Boolean specListWidth: Int studioWidth: Int wasBrowserSetInCLI: Boolean diff --git a/packages/frontend-shared/cypress/support/mock-graphql/clientTestContext.ts b/packages/frontend-shared/cypress/support/mock-graphql/clientTestContext.ts index 4f345a95477..c36e394714d 100644 --- a/packages/frontend-shared/cypress/support/mock-graphql/clientTestContext.ts +++ b/packages/frontend-shared/cypress/support/mock-graphql/clientTestContext.ts @@ -85,6 +85,7 @@ export function makeClientTestContext (): ClientTestContext { __typename: 'LocalSettingsPreferences', autoScrollingEnabled: true, isSideNavigationOpen: false, + showFetchRequests: true, desktopNotificationsEnabled: false, dismissNotificationBannerUntil: null, }, diff --git a/packages/reporter/cypress/e2e/commands.cy.ts b/packages/reporter/cypress/e2e/commands.cy.ts index 1ce8395c4a7..069eee2ac19 100644 --- a/packages/reporter/cypress/e2e/commands.cy.ts +++ b/packages/reporter/cypress/e2e/commands.cy.ts @@ -1087,4 +1087,59 @@ describe('commands', { viewportHeight: 1000 }, () => { cy.percySnapshot() }) }) + + context('show fetch requests', () => { + it('toggles visibility of fetch requests', () => { + addCommand(runner, { + name: 'visit', + renderProps: { + message: 'visit https://example.com', + }, + }) + + // Add fetch/request commands (event: true means it's a network request) + Array.from({ length: 3 }).forEach((_, index) => { + addCommand(runner, { + name: 'request', + event: true, + renderProps: { + indicator: 'successful', + wentToOrigin: true, + message: `GET /api/data/${index + 1}`, + }, + }) + }) + + cy.get('.command-name-visit').should('have.length', 2) + cy.contains('visit https://example.com').should('be.visible') + + cy.get('.command-name-request').should('have.length', 3) + cy.contains('GET /api/data/1').should('be.visible') + + cy.window().its('state.showFetchRequests').should('be.true') + + cy.get('[data-cy="runnable-options-button"]').click() + cy.get('[data-cy="more-options-runnable-popover"]').should('be.visible') + + cy.window().its('state.showFetchRequests').should('be.true') + + cy.get('[data-cy="show-http-requests-switch"]').click() + + cy.window().its('state.showFetchRequests').should('be.false') + + cy.get('.command-name-request').should('not.exist') + + // This one has event = true, so it should be visible + cy.contains('(xhr stub)GET --- /posts') + + cy.get('.command-name-visit').should('exist') + + cy.get('[data-cy="show-http-requests-switch"]').click() + + cy.window().its('state.showFetchRequests').should('be.true') + + cy.get('.command-name-request').should('have.length', 3) + cy.contains('GET /api/data/1').should('be.visible') + }) + }) }) diff --git a/packages/reporter/cypress/e2e/header.cy.ts b/packages/reporter/cypress/e2e/header.cy.ts index fd4f05fde47..240c20e4312 100755 --- a/packages/reporter/cypress/e2e/header.cy.ts +++ b/packages/reporter/cypress/e2e/header.cy.ts @@ -153,6 +153,28 @@ describe('header', () => { cy.percySnapshot() }) + it('shows when show fetch requests is enabled and can disable it', () => { + const switchSelector = '[data-cy=show-http-requests-switch]' + + cy.get('[data-cy="runnable-options-button"]').click() + cy.get('[data-cy="more-options-runnable-popover"]').should('be.visible') + + cy.get(switchSelector).invoke('attr', 'aria-checked').should('eq', 'true') + cy.get(switchSelector).click() + cy.get(switchSelector).invoke('attr', 'aria-checked').should('eq', 'false') + }) + + it('the show fetch requests toggle emits save:state event when clicked', () => { + cy.spy(runner, 'emit') + + cy.get('[data-cy="runnable-options-button"]').click() + cy.get('[data-cy="more-options-runnable-popover"]').should('be.visible') + + cy.get('[data-cy=show-http-requests-switch]').click() + cy.wrap(runner.emit).should('be.calledWith', 'save:state') + cy.percySnapshot() + }) + it('opens the open in IDE button', () => { cy.spy(runner, 'emit') diff --git a/packages/reporter/cypress/e2e/unit/app_state.cy.ts b/packages/reporter/cypress/e2e/unit/app_state.cy.ts index 4c43bdd0495..69ff6555fd0 100644 --- a/packages/reporter/cypress/e2e/unit/app_state.cy.ts +++ b/packages/reporter/cypress/e2e/unit/app_state.cy.ts @@ -152,6 +152,15 @@ describe('app state', () => { }) }) + context('#setShowFetchRequests', () => { + it('sets showFetchRequests', () => { + const instance = new AppState() + + instance.setShowFetchRequests(true) + expect(instance.showFetchRequests).to.eq(true) + }) + }) + context('#reset', () => { it('resets autoScrollingEnabled when it has not been toggled', () => { const instance = new AppState() diff --git a/packages/reporter/cypress/e2e/unit/events.cy.ts b/packages/reporter/cypress/e2e/unit/events.cy.ts index f22ee789117..29488c7f075 100644 --- a/packages/reporter/cypress/e2e/unit/events.cy.ts +++ b/packages/reporter/cypress/e2e/unit/events.cy.ts @@ -354,10 +354,12 @@ describe('events', () => { it('emits save:state on save:state', () => { appState.autoScrollingUserPref = false appState.isSpecsListOpen = true + appState.showFetchRequests = false events.emit('save:state') expect(runner.emit).to.have.been.calledWith('save:state', { autoScrollingEnabled: false, isSpecsListOpen: true, + showFetchRequests: false, }) }) diff --git a/packages/reporter/src/commands/command.tsx b/packages/reporter/src/commands/command.tsx index b5711d6d362..c5135e2387a 100644 --- a/packages/reporter/src/commands/command.tsx +++ b/packages/reporter/src/commands/command.tsx @@ -491,6 +491,10 @@ const Command: React.FC = observer(({ model, aliasesWithDuplicates } } + if (model.name === 'request' && model.event && !appState.showFetchRequests) { + return null + } + return ( <>
  • diff --git a/packages/reporter/src/lib/app-state.ts b/packages/reporter/src/lib/app-state.ts index 7dcf2631df8..f4e1e299fe0 100644 --- a/packages/reporter/src/lib/app-state.ts +++ b/packages/reporter/src/lib/app-state.ts @@ -33,6 +33,7 @@ class AppState { pinnedSnapshotId = defaults.pinnedSnapshotId studioActive = defaults.studioActive studioSingleTestActive = defaults.studioSingleTestActive + showFetchRequests = true isStopped = false hasBeenPaused = defaults.hasBeenPaused _resetAutoScrollingEnabledTo = true; @@ -49,6 +50,7 @@ class AppState { pinnedSnapshotId: observable, studioActive: observable, studioSingleTestActive: observable, + showFetchRequests: observable, hasBeenPaused: observable, }) } @@ -132,6 +134,14 @@ class AppState { this.studioSingleTestActive = studioSingleTestActive } + toggleShowFetchRequests () { + this.showFetchRequests = !this.showFetchRequests + } + + setShowFetchRequests (showFetchRequests: boolean) { + this.showFetchRequests = showFetchRequests + } + reset () { _.each(defaults, (value: any, key: string) => { this[key] = value diff --git a/packages/reporter/src/lib/events.ts b/packages/reporter/src/lib/events.ts index c11c0acc7fb..caa75c021e4 100644 --- a/packages/reporter/src/lib/events.ts +++ b/packages/reporter/src/lib/events.ts @@ -202,6 +202,7 @@ const events: Events = { // the "autoScrollingEnabled" key in `savedState` stores to the preference value itself, it is not the same as the "autoScrollingEnabled" variable stored in application state, which can be temporarily deactivated autoScrollingEnabled: appState.autoScrollingUserPref, isSpecsListOpen: appState.isSpecsListOpen, + showFetchRequests: appState.showFetchRequests, }) }) diff --git a/packages/reporter/src/main.tsx b/packages/reporter/src/main.tsx index 3bd3cac5842..aec2d327492 100644 --- a/packages/reporter/src/main.tsx +++ b/packages/reporter/src/main.tsx @@ -36,6 +36,7 @@ export interface BaseReporterProps { statsStore: StatsStore autoScrollingEnabled?: boolean isSpecsListOpen?: boolean + showFetchRequests?: boolean events: Events error?: RunnablesErrorModel resetStatsOnSpecChange?: boolean @@ -49,7 +50,7 @@ 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 = observer(({ appState = appStateDefault, runner, className, error, runMode = 'single', studioEnabled, autoScrollingEnabled, isSpecsListOpen, resetStatsOnSpecChange, renderReporterHeader = (props: ReporterHeaderProps) =>
    , runnerStore }) => { +const Reporter: React.FC = observer(({ appState = appStateDefault, runner, className, error, runMode = 'single', studioEnabled, autoScrollingEnabled, isSpecsListOpen, showFetchRequests, resetStatsOnSpecChange, renderReporterHeader = (props: ReporterHeaderProps) =>
    , runnerStore }) => { const previousSpecRunId = usePrevious(runnerStore.specRunId) const [isMounted, setIsMounted] = useState(false) const [isInitialized, setIsInitialized] = useState(false) @@ -81,6 +82,10 @@ const Reporter: React.FC = observer(({ appState = appStateD appState.setSpecsList(isSpecsListOpen ?? false) })() + action('set:show:fetch:requests', () => { + appState.setShowFetchRequests(showFetchRequests ?? true) + })() + shortcuts.start() runnablesStore.setRunningSpec(runnerStore.spec.relative) // we need to know when the test is mounted for our reporter tests. see diff --git a/packages/reporter/src/runnables/runnable-popover-options.tsx b/packages/reporter/src/runnables/runnable-popover-options.tsx index fb4d16a4015..5c030578a8d 100644 --- a/packages/reporter/src/runnables/runnable-popover-options.tsx +++ b/packages/reporter/src/runnables/runnable-popover-options.tsx @@ -66,8 +66,10 @@ export const RunnablePopoverOptions: React.FC = observer(({ events.emit('save:state') } - // TODO: to be implemented - // const toggleShowHttpRequests = () => {} + const toggleShowFetchRequests = () => { + appState.toggleShowFetchRequests() + events.emit('save:state') + } // Close popover when clicking outside useEffect(() => { @@ -135,20 +137,18 @@ export const RunnablePopoverOptions: React.FC = observer(({
    Testing preferences
    - {/* // TODO: to be implemented */} - {/*
    +
    Show HTTP requests
    -
    */} +
    @@ -158,7 +158,6 @@ export const RunnablePopoverOptions: React.FC = observer(({
    diff --git a/packages/types/src/driver.ts b/packages/types/src/driver.ts index 62575b931e7..9402dbbc0fa 100644 --- a/packages/types/src/driver.ts +++ b/packages/types/src/driver.ts @@ -13,6 +13,7 @@ interface MochaRunnerState { export type RunState = MochaRunnerState & ReporterRunState & { isSpecsListOpen?: boolean + showFetchRequests?: boolean } export interface Emissions { diff --git a/packages/types/src/preferences.ts b/packages/types/src/preferences.ts index f1e8dc253f8..792a26035b6 100644 --- a/packages/types/src/preferences.ts +++ b/packages/types/src/preferences.ts @@ -7,6 +7,7 @@ export type NotifyWhenRunCompletes = typeof NotifyCompletionStatuses[number] export const defaultPreferences: AllowedState = { autoScrollingEnabled: true, isSpecsListOpen: false, + showFetchRequests: true, isSideNavigationOpen: true, desktopNotificationsEnabled: null, notifyWhenRunStarts: false, @@ -35,6 +36,7 @@ export const allowedKeys: Readonly> = [ 'showedStudioModal', 'preferredOpener', 'isSpecsListOpen', + 'showFetchRequests', 'firstOpened', 'lastOpened', 'lastProjectId', @@ -62,6 +64,7 @@ export type AllowedState = Partial<{ appX: Maybe appY: Maybe isSpecsListOpen: Maybe + showFetchRequests: Maybe autoScrollingEnabled: Maybe banners: Maybe browserWidth: Maybe diff --git a/packages/types/src/reporter.ts b/packages/types/src/reporter.ts index 980e573359b..aa55b784808 100644 --- a/packages/types/src/reporter.ts +++ b/packages/types/src/reporter.ts @@ -16,4 +16,5 @@ export interface ReporterStartInfo extends StatsStoreStartInfo { scrollTop: number studioActive: boolean studioSingleTestActive: boolean + showFetchRequests: boolean }