From 0dd7d89ea25f70b34caa9fb82165d23246afb17a Mon Sep 17 00:00:00 2001
From: Jennifer Shehane
Date: Fri, 9 May 2025 16:00:51 -0400
Subject: [PATCH 01/48] misc: begin work on reporter redesign
---
packages/reporter/README.md | 14 ------
packages/reporter/src/attempts/attempts.scss | 2 +-
.../reporter/src/collapsible/collapsible.tsx | 6 ++-
packages/reporter/src/hooks/hooks.scss | 2 +-
.../reporter/src/instruments/instruments.scss | 2 +-
packages/reporter/src/lib/util.ts | 8 ----
.../src/runnables/runnable-and-suite.tsx | 11 ++---
.../reporter/src/runnables/runnable-model.ts | 4 ++
.../reporter/src/runnables/runnables-store.ts | 27 ++++++++++-
.../reporter/src/runnables/runnables.scss | 45 +++++++++++++++----
packages/reporter/src/test/test.tsx | 5 +--
11 files changed, 81 insertions(+), 45 deletions(-)
diff --git a/packages/reporter/README.md b/packages/reporter/README.md
index afdcc2b5758a..0b4b294f4abe 100644
--- a/packages/reporter/README.md
+++ b/packages/reporter/README.md
@@ -16,20 +16,6 @@ The reporter shows the running results of the tests. It includes the following:
- commands and assertions with detailed information
- any failures/errors
-## Building
-
-### For development
-
-```bash
-yarn workspace @packages/reporter build
-```
-
-### For production
-
-```bash
-yarn workspace @packages/reporter build-prod
-```
-
## Developing
To see the reporter render, see [Developing the driver](../driver/README.md#Developing).
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index f88e9ee11762..92b3cc8afc25 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -107,7 +107,7 @@
border-radius: 7px;
box-shadow: 0 1px 1px 0 rgba($white, 0.20);
display: flex;
- font-size: 11px;
+ font-size: 12px;
padding: 2px 5px;
position: relative;
background-color: $black;
diff --git a/packages/reporter/src/collapsible/collapsible.tsx b/packages/reporter/src/collapsible/collapsible.tsx
index 7c2125a13207..11afd208933a 100644
--- a/packages/reporter/src/collapsible/collapsible.tsx
+++ b/packages/reporter/src/collapsible/collapsible.tsx
@@ -2,6 +2,7 @@ import cs from 'classnames'
import React, { CSSProperties, MouseEvent, ReactNode, RefObject, useCallback, useState } from 'react'
import { onEnterOrSpace } from '../lib/util'
import ChevronIcon from '@packages/frontend-shared/src/assets/icons/chevron-down-small_x8.svg'
+import DocumentBlankIcon from '@packages/frontend-shared/src/assets/icons/document-blank_x16.svg'
interface CollapsibleProps {
isOpen?: boolean
@@ -42,11 +43,12 @@ const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false,
tabIndex={0}
>
- {!hideExpander &&
}
+ {!hideExpander && headerClass === 'hook-header' &&
}
+ {!hideExpander && headerClass !== 'hook-header' &&
}
{header}
diff --git a/packages/reporter/src/hooks/hooks.scss b/packages/reporter/src/hooks/hooks.scss
index 84b011bcaf0f..bebe1840c76f 100644
--- a/packages/reporter/src/hooks/hooks.scss
+++ b/packages/reporter/src/hooks/hooks.scss
@@ -27,7 +27,7 @@
color: $gray-400;
display: inline-block;
flex-grow: 1;
- font-size: 11px;
+ font-size: 12px;
cursor: pointer;
padding: 4px 0;
diff --git a/packages/reporter/src/instruments/instruments.scss b/packages/reporter/src/instruments/instruments.scss
index bf222b365f6f..780ac8f0e428 100644
--- a/packages/reporter/src/instruments/instruments.scss
+++ b/packages/reporter/src/instruments/instruments.scss
@@ -21,7 +21,7 @@
td {
font-family: $monospace;
- font-size: 11px;
+ font-size: 12px;
}
}
diff --git a/packages/reporter/src/lib/util.ts b/packages/reporter/src/lib/util.ts
index dbef553a2b60..226db711e508 100644
--- a/packages/reporter/src/lib/util.ts
+++ b/packages/reporter/src/lib/util.ts
@@ -1,12 +1,5 @@
import type { KeyboardEvent } from 'react'
-const INDENT_BASE = 5
-const INDENT_AMOUNT = 15
-
-function indent (level: number) {
- return INDENT_BASE + level * INDENT_AMOUNT
-}
-
// Returns a keyboard handler that invokes the provided function when either enter or space is pressed
const onEnterOrSpace = (f: (() => void)) => {
return (e: KeyboardEvent) => {
@@ -74,6 +67,5 @@ const getFilenameParts = (spec: string): [string, string] => {
export {
formatDuration,
getFilenameParts,
- indent,
onEnterOrSpace,
}
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index ec006923a97e..a5710ebee285 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -3,8 +3,6 @@ import _ from 'lodash'
import { observer } from 'mobx-react'
import React, { MouseEvent, useCallback } from 'react'
-import { indent } from '../lib/util'
-
import appState, { AppState } from '../lib/app-state'
import events, { Events } from '../lib/events'
import Test from '../test/test'
@@ -48,7 +46,7 @@ const Suite: React.FC
= observer(({ eventManager = events, model, st
@@ -68,8 +66,8 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
Suite.displayName = 'Suite'
export interface RunnableProps {
+ appState?: AppState
model: TestModel | SuiteModel
- appState: AppState
studioEnabled: boolean
canSaveStudioLogs: boolean
}
@@ -89,7 +87,10 @@ const Runnable: React.FC = observer(({ appState: appStateProps =
>
{model.type === 'test'
?
- : }
+ : }
)
})
diff --git a/packages/reporter/src/runnables/runnable-model.ts b/packages/reporter/src/runnables/runnable-model.ts
index 12e2fb6fb484..f3f98acaeaa8 100644
--- a/packages/reporter/src/runnables/runnable-model.ts
+++ b/packages/reporter/src/runnables/runnable-model.ts
@@ -5,6 +5,7 @@ export interface RunnableProps {
id: string
title?: string
hooks: Array
+ parentTitle?: string
}
export default class Runnable {
@@ -12,6 +13,7 @@ export default class Runnable {
title?: string
level: number
hooks: Array = []
+ parentTitle?: string
constructor (props: RunnableProps, level: number) {
makeObservable(this, {
@@ -19,11 +21,13 @@ export default class Runnable {
title: observable,
level: observable,
hooks: observable,
+ parentTitle: observable,
})
this.id = props.id
this.title = props.title
this.level = level
this.hooks = props.hooks
+ this.parentTitle = props.parentTitle
}
}
diff --git a/packages/reporter/src/runnables/runnables-store.ts b/packages/reporter/src/runnables/runnables-store.ts
index ea04a6ff01d6..ff139c17f31a 100644
--- a/packages/reporter/src/runnables/runnables-store.ts
+++ b/packages/reporter/src/runnables/runnables-store.ts
@@ -126,7 +126,32 @@ export class RunnablesStore {
}
_createSuite (props: SuiteProps, level: number) {
- const suite = new SuiteModel(props, level)
+ // Get parent suite titles by traversing up the queue
+ const parentTitles: string[] = []
+
+ // Find the immediate parent suite by looking for the last suite at a lower level
+ let parentLevel = level - 1
+
+ for (let i = this._runnablesQueue.length - 1; i >= 0; i--) {
+ const runnable = this._runnablesQueue[i]
+
+ if ('type' in runnable && runnable.type === 'suite' && runnable.level === parentLevel && runnable.title) {
+ // Add this parent's title
+ parentTitles.unshift(runnable.title)
+ break
+ }
+ }
+
+ // Combine parent titles with current suite title
+ const hierarchicalTitle = [...parentTitles, props.title].join(' > ')
+
+ // Create new props with the hierarchical title
+ const suiteProps = {
+ ...props,
+ title: hierarchicalTitle,
+ }
+
+ const suite = new SuiteModel(suiteProps, level)
this._runnablesQueue.push(suite)
suite.children = this._createRunnableChildren(props, ++level)
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 784ffe7e8873..09ea0d09d20a 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -93,17 +93,19 @@
.runnable-wrapper {
border-left: 4px solid transparent;
- padding: 0 0 0 4px;
+ padding: 0;
.collapsible-header {
&:focus {
.collapsible-header-inner {
- background-color: $gray-1100;
+ background-color: $gray-1000;
cursor: pointer;
}
}
.collapsible-header-inner {
+ padding: 8px !important;
+ background-color: $gray-1000;
&:hover {
background-color: $gray-900;
cursor: pointer;
@@ -118,7 +120,6 @@
width: 100%;
}
}
-
&:hover {
.runnable-controls-studio {
opacity: 0.5;
@@ -146,18 +147,30 @@
margin-right: 5px;
min-width: 12px;
text-align: center;
- font-size: 11px;
+ font-size: 12px;
}
&.suite .collapsible-indicator {
margin-left: 2px;
- .icon-dark {
- stroke: $gray-800;
+ // .icon-dark {
+ // stroke: $gray-400;
+ // }
+ .icon-light {
+ fill: $gray-400;
}
}
+ &> div > .runnable-wrapper {
+ border: 1px solid $gray-950;
+ border-radius: 4px;
+ border-left: 4px solid transparent;
+ margin-top: 2px;
+ margin-bottom: 2px;
+ }
+
&.runnable-failed > div > .runnable-wrapper,
&.runnable-failed > div > .runnable-instruments {
+
border-left: 4px solid $fail;
}
@@ -190,13 +203,22 @@
&.runnable-skipped > div > .runnable-wrapper,
&.runnable-skipped > div > .runnable-instruments {
+ border: 1px solid $gray-950;
border-left: 4px solid $gray-500;
}
+ &.suite.runnable {
+ margin-bottom: 8px;
+ }
&.suite > div > .runnable-wrapper {
+ border: 0;
+ margin: 0;
+ border-radius: 0;
+ background-color: $gray-1100;
+
.runnable-title {
- color: $gray-50;
- font-size: 13px;
+ color: $gray-400;
+ font-size: 14px;
}
}
@@ -256,8 +278,9 @@
}
.runnable-title {
+ color: $white;
font-family: $font-system;
- font-size: 12.5px;
+ font-size: 14px;
min-width: $reporter-contents-min-width;
white-space: pre-line;
@@ -278,6 +301,10 @@
}
}
+ .wrap>.runnables {
+ padding: 4px;
+ }
+
.suite > div .runnable-wrapper,
.test .runnable-wrapper > .collapsible-header {
text-overflow: ellipsis;
diff --git a/packages/reporter/src/test/test.tsx b/packages/reporter/src/test/test.tsx
index fb53087d8869..aa3ce573c076 100644
--- a/packages/reporter/src/test/test.tsx
+++ b/packages/reporter/src/test/test.tsx
@@ -7,7 +7,6 @@ import cs from 'classnames'
import events, { Events } from '../lib/events'
import appState, { AppState } from '../lib/app-state'
import Collapsible from '../collapsible/collapsible'
-import { indent } from '../lib/util'
import TestModel from './test-model'
import scroller, { Scroller } from '../lib/scroller'
@@ -173,13 +172,13 @@ const Test: React.FC = observer(({ model, events: eventsProps = event
containerRef={containerRef}
header={_header()}
headerClass='runnable-wrapper'
- headerStyle={{ paddingLeft: indent(model.level) }}
+ headerStyle={{ }}
contentClass='runnable-instruments'
isOpen={model.isOpen}
onOpenStateChangeRequested={(isOpen: boolean) => model.setIsOpen(isOpen)}
hideExpander
>
-
+
_scrollIntoView()} />
{appStateProps.studioActive && }
From 2b4137252f5636db3e13758e86c4781269a3763a Mon Sep 17 00:00:00 2001
From: Jennifer Shehane
Date: Tue, 13 May 2025 12:43:17 -0400
Subject: [PATCH 02/48] remove info icon on failing tests
---
packages/reporter/src/test/test.tsx | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/packages/reporter/src/test/test.tsx b/packages/reporter/src/test/test.tsx
index aa3ce573c076..b00deac8e759 100644
--- a/packages/reporter/src/test/test.tsx
+++ b/packages/reporter/src/test/test.tsx
@@ -16,7 +16,6 @@ import { LaunchStudioIcon } from '../components/LaunchStudioIcon'
import CheckIcon from '@packages/frontend-shared/src/assets/icons/checkmark_x16.svg'
import ClipboardIcon from '@packages/frontend-shared/src/assets/icons/general-clipboard_x16.svg'
-import WarningIcon from '@packages/frontend-shared/src/assets/icons/warning_x16.svg'
interface StudioControlsProps {
events?: Events
@@ -136,16 +135,6 @@ const Test: React.FC = observer(({ model, events: eventsProps = event
const _controls = () => {
let controls: Array = []
- if (model.state === 'failed') {
- controls.push(
-
-
-
-
- ,
- )
- }
-
if (studioEnabled && !appStateProps.studioActive) {
controls.push(
Date: Tue, 13 May 2025 12:45:02 -0400
Subject: [PATCH 03/48] Add new queued icon to tests
---
.../assets/icons/status-processing_x12.svg | 3 --
packages/reporter/package.json | 1 +
packages/reporter/src/lib/state-icon.tsx | 6 ++-
.../reporter/src/runnables/runnables.scss | 41 +++++++++++++++----
yarn.lock | 21 ++++++++--
5 files changed, 54 insertions(+), 18 deletions(-)
delete mode 100644 packages/frontend-shared/src/assets/icons/status-processing_x12.svg
diff --git a/packages/frontend-shared/src/assets/icons/status-processing_x12.svg b/packages/frontend-shared/src/assets/icons/status-processing_x12.svg
deleted file mode 100644
index 2b33cc2eb4fe..000000000000
--- a/packages/frontend-shared/src/assets/icons/status-processing_x12.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/packages/reporter/package.json b/packages/reporter/package.json
index 906cd6cc4626..630c38c2f68e 100644
--- a/packages/reporter/package.json
+++ b/packages/reporter/package.json
@@ -15,6 +15,7 @@
"watch": "yarn build-for-tests --watch --progress"
},
"devDependencies": {
+ "@cypress-design/react-icon": "^1.19.0",
"@cypress/react-tooltip": "0.5.3",
"@fontsource/mulish": "4.3.0",
"@fontsource/open-sans": "4.3.0",
diff --git a/packages/reporter/src/lib/state-icon.tsx b/packages/reporter/src/lib/state-icon.tsx
index 1da90dafa3fa..47b414c5d9d4 100644
--- a/packages/reporter/src/lib/state-icon.tsx
+++ b/packages/reporter/src/lib/state-icon.tsx
@@ -6,9 +6,9 @@ import type { TestState } from '@packages/types'
import FailedIcon from '@packages/frontend-shared/src/assets/icons/status-failed_x12.svg'
import PassedIcon from '@packages/frontend-shared/src/assets/icons/status-passed_x12.svg'
import PendingIcon from '@packages/frontend-shared/src/assets/icons/status-pending_x12.svg'
-import ProcessingIcon from '@packages/frontend-shared/src/assets/icons/status-processing_x12.svg'
import RunningIcon from '@packages/frontend-shared/src/assets/icons/status-running_x12.svg'
import WandIcon from '@packages/frontend-shared/src/assets/icons/object-magic-wand-dark-mode_x16.svg'
+import { IconStatusQueuedOutline } from '@cypress-design/react-icon'
interface Props extends React.HTMLProps {
state: TestState
@@ -50,7 +50,9 @@ const StateIcon: React.FC = observer((props: Props) => {
if (state === 'processing') {
return (
-
+
)
}
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 09ea0d09d20a..9f7351e8e947 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -120,13 +120,11 @@
width: 100%;
}
}
- &:hover {
- .runnable-controls-studio {
- opacity: 0.5;
+ .runnable-controls-studio {
+ opacity: 0.5;
- &:hover {
- opacity: 1;
- }
+ &:hover {
+ opacity: 1;
}
}
}
@@ -220,6 +218,22 @@
color: $gray-400;
font-size: 14px;
}
+
+ .collapsible-header-inner {
+ .runnable-controls-studio {
+ opacity: 0;
+ }
+
+ &:hover {
+ .runnable-controls-studio {
+ opacity: 0.5;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+ }
}
&.test.runnable-passed.runnable-studio {
@@ -313,8 +327,6 @@
}
.runnable-controls {
- float: right;
- height: 18px;
label {
padding: 2px 4px;
@@ -328,8 +340,19 @@
}
.runnable-controls-studio {
- color: $purple-300;
+ display: flex;
+ height: 20px;
+ width: 20px;
+ color: $gray-500;
+ border: 1px solid $gray-900;
+ border-radius: 4px;
opacity: 0;
+ padding-top: 2px;
+ padding-left: 1px;
+
+ svg {
+ flex: auto;
+ }
}
}
diff --git a/yarn.lock b/yarn.lock
index 4b40dcff007c..6b3625a93ecc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2681,13 +2681,21 @@
tailwindcss "^3.4.3"
tailwindcss-hocus "^0.0.7"
-"@cypress-design/icon-registry@^1.0.0", "@cypress-design/icon-registry@^1.18.0", "@cypress-design/icon-registry@^1.5.1":
- version "1.18.0"
- resolved "https://registry.yarnpkg.com/@cypress-design/icon-registry/-/icon-registry-1.18.0.tgz#799c5ac8f8362aebdcf2181119c3205136ca5ab9"
- integrity sha512-4goChP9rWVq7F/+c36JyJ4quvHSyI6gkjJ/IKFqncNwkC3gvVeJ4GQX2mqQJCQ+z0Er+2Mmzcw7JiVo1GpbJlg==
+"@cypress-design/icon-registry@^1.0.0", "@cypress-design/icon-registry@^1.18.0", "@cypress-design/icon-registry@^1.19.0", "@cypress-design/icon-registry@^1.5.1":
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/@cypress-design/icon-registry/-/icon-registry-1.19.0.tgz#43949b941e0f67e6e269377b020bb33682ab7f7b"
+ integrity sha512-B8HCbjH0uobkrv5KogHUvTU9q/tGPAMWjWTv6Rt9MGphM7du2nWvosK/+Lbx71VhUFXZoU5QBsmGOK7YlGkXsA==
dependencies:
"@cypress-design/color-constants" "^1.1.0"
+"@cypress-design/react-icon@^1.19.0":
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/@cypress-design/react-icon/-/react-icon-1.19.0.tgz#a66256b5791e03b483bc1c69ff6dcbd3ff165e49"
+ integrity sha512-HIpi8iDGDgvbzNgYXDUq9Mnvq64gYhb5mKUfWSuor7MRi5QKLsjnkIYqPgXuFRjzYZJ4hXBufPPMoOIKIsT9bA==
+ dependencies:
+ "@cypress-design/icon-registry" "^1.19.0"
+ clsx "^2.1.1"
+
"@cypress-design/vue-button@^1.1.0", "@cypress-design/vue-button@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@cypress-design/vue-button/-/vue-button-1.6.0.tgz#e7266dfe11c31628ef3a979fffcf041b141e39c3"
@@ -12638,6 +12646,11 @@ cloneable-readable@^1.0.0:
process-nextick-args "^2.0.0"
readable-stream "^2.3.5"
+clsx@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
+ integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
+
cmd-shim@6.0.3, cmd-shim@^6.0.0:
version "6.0.3"
resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.3.tgz#c491e9656594ba17ac83c4bd931590a9d6e26033"
From 5da0904ff4f261e4e2c7239648e40f2830b6c827 Mon Sep 17 00:00:00 2001
From: Jennifer Shehane
Date: Fri, 16 May 2025 11:37:10 -0400
Subject: [PATCH 04/48] bump react-icon
---
packages/reporter/package.json | 2 +-
yarn.lock | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/packages/reporter/package.json b/packages/reporter/package.json
index 630c38c2f68e..85166477a2e3 100644
--- a/packages/reporter/package.json
+++ b/packages/reporter/package.json
@@ -15,7 +15,7 @@
"watch": "yarn build-for-tests --watch --progress"
},
"devDependencies": {
- "@cypress-design/react-icon": "^1.19.0",
+ "@cypress-design/react-icon": "^1.21.0",
"@cypress/react-tooltip": "0.5.3",
"@fontsource/mulish": "4.3.0",
"@fontsource/open-sans": "4.3.0",
diff --git a/yarn.lock b/yarn.lock
index 6b3625a93ecc..4f512ac36c7a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2681,19 +2681,19 @@
tailwindcss "^3.4.3"
tailwindcss-hocus "^0.0.7"
-"@cypress-design/icon-registry@^1.0.0", "@cypress-design/icon-registry@^1.18.0", "@cypress-design/icon-registry@^1.19.0", "@cypress-design/icon-registry@^1.5.1":
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/@cypress-design/icon-registry/-/icon-registry-1.19.0.tgz#43949b941e0f67e6e269377b020bb33682ab7f7b"
- integrity sha512-B8HCbjH0uobkrv5KogHUvTU9q/tGPAMWjWTv6Rt9MGphM7du2nWvosK/+Lbx71VhUFXZoU5QBsmGOK7YlGkXsA==
+"@cypress-design/icon-registry@^1.0.0", "@cypress-design/icon-registry@^1.18.0", "@cypress-design/icon-registry@^1.21.0", "@cypress-design/icon-registry@^1.5.1":
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/@cypress-design/icon-registry/-/icon-registry-1.21.0.tgz#6f815fa1bffe40eab9507d9ec26fd9aff4a6ec62"
+ integrity sha512-zgbNhRCFmaby9QXpzGcT0u3ancmvPIq1bkFTSylChjgK2vvv+iQqmSnAZGrg7Zczd9McUUdTiXy0N1lzqbjAvA==
dependencies:
"@cypress-design/color-constants" "^1.1.0"
-"@cypress-design/react-icon@^1.19.0":
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/@cypress-design/react-icon/-/react-icon-1.19.0.tgz#a66256b5791e03b483bc1c69ff6dcbd3ff165e49"
- integrity sha512-HIpi8iDGDgvbzNgYXDUq9Mnvq64gYhb5mKUfWSuor7MRi5QKLsjnkIYqPgXuFRjzYZJ4hXBufPPMoOIKIsT9bA==
+"@cypress-design/react-icon@^1.21.0":
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/@cypress-design/react-icon/-/react-icon-1.21.0.tgz#24a454692c5c6f383b8645ad4bf488412144e641"
+ integrity sha512-YbEBEfmLFMO+EK5GZ10nveDQEJItAWOej5ue5Jutu9CEh3WjSCFafaFAZhBf9byOhP78UK77c4gk4b18I0nCDw==
dependencies:
- "@cypress-design/icon-registry" "^1.19.0"
+ "@cypress-design/icon-registry" "^1.21.0"
clsx "^2.1.1"
"@cypress-design/vue-button@^1.1.0", "@cypress-design/vue-button@^1.6.0":
From d786ef712962f56507187b620301c43bf567d940 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Thu, 5 Jun 2025 17:25:00 -0400
Subject: [PATCH 05/48] add some styles for the header
---
packages/reporter/package.json | 2 +
.../reporter/src/header/DebugDismiss.scss | 17 +-
packages/reporter/src/header/header.scss | 181 ++++++++++--------
packages/reporter/src/header/header.tsx | 66 ++++---
packages/reporter/src/lib/base.scss | 35 ++--
packages/reporter/src/main.tsx | 8 +-
.../src/runnables/runnable-header.tsx | 8 +-
.../reporter/src/runnables/runnables.scss | 27 ---
packages/reporter/src/runnables/runnables.tsx | 6 +-
9 files changed, 178 insertions(+), 172 deletions(-)
diff --git a/packages/reporter/package.json b/packages/reporter/package.json
index 85166477a2e3..29b760936980 100644
--- a/packages/reporter/package.json
+++ b/packages/reporter/package.json
@@ -15,6 +15,8 @@
"watch": "yarn build-for-tests --watch --progress"
},
"devDependencies": {
+ "@cypress-design/constants-button": "^1.9.0",
+ "@cypress-design/react-button": "^1.10.1",
"@cypress-design/react-icon": "^1.21.0",
"@cypress/react-tooltip": "0.5.3",
"@fontsource/mulish": "4.3.0",
diff --git a/packages/reporter/src/header/DebugDismiss.scss b/packages/reporter/src/header/DebugDismiss.scss
index 237763b33db5..f83efe2be234 100644
--- a/packages/reporter/src/header/DebugDismiss.scss
+++ b/packages/reporter/src/header/DebugDismiss.scss
@@ -1,15 +1,16 @@
.debug-dismiss {
- display: flex !important;
+ display: flex;
align-items: center;
- font-size: 12px !important;
- font-weight: 600 !important;
- line-height: 16px !important;
- color: #9AA2FC !important;
- border: solid 1px #9AA2FC !important;
- border-radius: 16px !important;
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 16px;
+ color: $indigo-300;
+ border: solid 1px $indigo-300;
+ border-radius: 16px;
gap: 4px;
+ padding: 4px 8px;
.delete-icon path {
- fill: #9AA2FC
+ fill: $indigo-300;
}
}
\ No newline at end of file
diff --git a/packages/reporter/src/header/header.scss b/packages/reporter/src/header/header.scss
index 82d1417cc763..18d18431062b 100644
--- a/packages/reporter/src/header/header.scss
+++ b/packages/reporter/src/header/header.scss
@@ -1,17 +1,17 @@
$color-transition: color 150ms ease-out;
.reporter {
- header {
+ .spec-container {
background-color: $gray-1100;
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
- gap: 8px;
+ gap: 13px;
font-family: $font-system;
min-height: $header-height;
outline: 0;
overflow: hidden;
- padding: 20px 16px;
+ padding: 16px;
width: 100%;
z-index: 1;
@@ -19,69 +19,38 @@ $color-transition: color 150ms ease-out;
flex-grow: 2;
}
- button {
- background-color: transparent;
- border-color: transparent;
- border-radius: 0;
- display: inline-block;
- font-weight: 300;
- line-height: 26px;
- outline: 0;
- padding: 0 8px;
- text-align: center;
-
- &:hover {
- background-color: $gray-900;
- }
-
- &[disabled],
- &[disabled]:hover,
- &[disabled]:active {
- background: none;
- box-shadow: none;
- color: $gray-500;
- }
- }
+ // TODO: check the impact of removing this
+ // button {
+ // background-color: transparent;
+ // border-color: transparent;
+ // border-radius: 0;
+ // display: inline-block;
+ // font-weight: 300;
+ // line-height: 26px;
+ // outline: 0;
+ // padding: 0 8px;
+ // text-align: center;
+
+ // &:hover {
+ // background-color: $gray-900;
+ // }
+
+ // &[disabled],
+ // &[disabled]:hover,
+ // &[disabled]:active {
+ // background: none;
+ // box-shadow: none;
+ // color: $gray-500;
+ // }
+ // }
}
- .toggle-specs-wrapper {
- display: flex;
- height: 24px;
-
- button {
- color: $gray-700;
- font-size: 16px;
- font-weight: 300;
- padding-left: 0;
- padding-right: 8px;
- transition: $color-transition;
- width: auto !important;
-
- &:focus,
- &:hover {
- background-color: initial;
-
- svg {
- color: $gray-400;
- transition: $color-transition;
- }
-
- .toggle-specs-text {
- color: $gray-400;
- transition: $color-transition;
- }
- }
-
- .toggle-specs-text {
- color: $gray-500;
- transition: $color-transition;
- }
-
- svg {
- margin-right: 8px;
- margin-bottom: -2px;
- }
- }
+ .statsAndControls {
+ display: inline-flex;
+ width: 100%;
+ justify-content: space-between;
+ padding: 20px 16px;
+ border: 1px solid #2E3247;
}
.stats {
@@ -92,27 +61,19 @@ $color-transition: color 150ms ease-out;
flex-wrap: wrap;
height: 24px;
justify-content: space-between;
- padding: 0 4px;
- min-width: 124px;
li {
display: flex;
- font-size: 12px;
- font-weight: 600;
+ align-items: center;
+ font-size: 14px;
+ font-weight: 700;
list-style-type: none;
- padding: 0 4px;
-
- svg {
- margin-right: 2px;
- }
+ padding: 2px 8px;
+ gap: 4px;
+ line-height: 20px;
.num {
- color: $white;
- line-height: 12px;
- vertical-align: text-top;
- min-width: 16px;
- display: inline-block;
- text-align: center;
+ color: $gray-400;
&.empty {
color: $gray-800;
@@ -157,4 +118,64 @@ $color-transition: color 150ms ease-out;
}
}
}
-}
+
+ .runnable-header {
+ @include inner-header;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0;
+ position: unset;
+ line-height: 20px;
+ min-width: 0;
+ align-items: center;
+ flex: 1;
+
+
+ >*:first-child {
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ span>span>a>svg {
+ margin-bottom: -2px;
+ margin-right: 8px;
+ }
+
+ a,
+ a:active,
+ a:focus,
+ a:hover {
+ color: $gray-500;
+ font-weight: 300;
+
+ strong {
+ color: $white;
+ font-weight: 500;
+ }
+ }
+
+ .duration {
+ border: 1px solid $gray-900;
+ border-radius: 18px;
+ color: $gray-400;
+ font-size: 12px;
+ font-weight: 500;
+ line-height: 20px;
+ padding: 0 8px;
+ font-variant-numeric: tabular-nums;
+ }
+ }
+
+ .toggle-specs-wrapper {
+ .toggle-specs-button {
+ padding: 0;
+ width: 32px;
+ justify-content: center;
+ color: $gray-500;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/reporter/src/header/header.tsx b/packages/reporter/src/header/header.tsx
index 678d347f21de..b7d0a574a696 100644
--- a/packages/reporter/src/header/header.tsx
+++ b/packages/reporter/src/header/header.tsx
@@ -2,50 +2,56 @@ import { observer } from 'mobx-react'
import React from 'react'
// @ts-ignore
import Tooltip from '@cypress/react-tooltip'
-
-import MenuExpandRightIcon from '@packages/frontend-shared/src/assets/icons/menu-expand-right_x16.svg'
-
+// import Tooltip from '@cypress-design/react-tooltip'
+import Button from '@cypress-design/react-button'
import defaultEvents, { Events } from '../lib/events'
import type { AppState } from '../lib/app-state'
import { action } from 'mobx'
-
-import Controls from './controls'
-import Stats from './stats'
import type { StatsStore } from './stats-store'
-import { DebugDismiss } from './DebugDismiss'
import type { RunnablesStore } from '../runnables/runnables-store'
+import RunnableHeader from '../runnables/runnable-header'
+import MenuExpandRightIcon from '@packages/frontend-shared/src/assets/icons/menu-expand-right_x16.svg'
+import Stats from './stats'
+import Controls from './controls'
export interface ReporterHeaderProps {
appState: AppState
events?: Events
statsStore: StatsStore
runnablesStore: RunnablesStore
+ spec?: Cypress.Cypress['spec']
}
-const Header: React.FC = observer(({ appState, events = defaultEvents, statsStore, runnablesStore }: ReporterHeaderProps) => (
-
- {appState.isSpecsListOpen ? 'Collapse' : 'Expand'} Specs List F } wrapperClassName='toggle-specs-wrapper' className='cy-tooltip'>
- {
- action('toggle:spec:list', () => {
- appState.toggleSpecList()
- events.emit('save:state')
- })()
- }
- }>
-
-
- Specs
-
-
-
- {runnablesStore.testFilter && runnablesStore.totalTests > 0 && }
-
-
+const Header: React.FC = observer(({ appState, events = defaultEvents, statsStore, runnablesStore, spec }: ReporterHeaderProps) => {
+ return
+
+
{appState.isSpecsListOpen ? 'Collapse' : 'Expand'} Specs List F } wrapperClassName='toggle-specs-wrapper' className='cy-tooltip'>
+
+ {
+ action('toggle:spec:list', () => {
+ appState.toggleSpecList()
+ events.emit('save:state')
+ })()
+ }
+ }>
+
+
+
+
+ {spec &&
}
+
+
+
+
+
-))
+})
Header.displayName = 'Header'
diff --git a/packages/reporter/src/lib/base.scss b/packages/reporter/src/lib/base.scss
index 04dcdb629809..e83685b17f55 100644
--- a/packages/reporter/src/lib/base.scss
+++ b/packages/reporter/src/lib/base.scss
@@ -56,23 +56,24 @@ body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input
font-style: italic;
}
- button {
- background: $black;
- border: none;
- border-radius: 2px;
- color: $gray-200;
- cursor: pointer;
- display: inline-block;
- font-size: 14px;
- font-weight: 500;
- line-height: 1.4;
- padding: 10px 16px;
- text-align: center;
- touch-action: manipulation;
- vertical-align: middle;
- white-space: nowrap;
- user-select: none;
- }
+ // TODO: check the impact of removing this
+ // button {
+ // background: $black;
+ // border: none;
+ // border-radius: 2px;
+ // color: $gray-200;
+ // cursor: pointer;
+ // display: inline-block;
+ // font-size: 14px;
+ // font-weight: 500;
+ // line-height: 1.4;
+ // padding: 10px 16px;
+ // text-align: center;
+ // touch-action: manipulation;
+ // vertical-align: middle;
+ // white-space: nowrap;
+ // user-select: none;
+ // }
h1, h2, h3, h4, h5, h6 {
font-weight: 300;
diff --git a/packages/reporter/src/main.tsx b/packages/reporter/src/main.tsx
index fd48db362bb2..4758477bc1a2 100644
--- a/packages/reporter/src/main.tsx
+++ b/packages/reporter/src/main.tsx
@@ -47,12 +47,12 @@ export interface BaseReporterProps {
runnerStore: MobxRunnerStore
}
-export interface SingleReporterProps extends BaseReporterProps{
+export interface SingleReporterProps extends BaseReporterProps {
runMode?: 'single'
}
// 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, resetStatsOnSpecChange, renderReporterHeader = (props: ReporterHeaderProps) => , runnerStore }) => {
const previousSpecRunId = usePrevious(runnerStore.specRunId)
const [isMounted, setIsMounted] = useState(false)
const [isInitialized, setIsInitialized] = useState(false)
@@ -101,7 +101,7 @@ const Reporter: React.FC = observer(({ appState = appStateD
runnablesStore.setRunningSpec(runnerStore.spec.relative)
if (
resetStatsOnSpecChange &&
- runnerStore.specRunId !== previousSpecRunId
+ runnerStore.specRunId !== previousSpecRunId
) {
statsStore.reset()
}
@@ -112,7 +112,7 @@ const Reporter: React.FC = observer(({ appState = appStateD
'studio-active': appState.studioActive,
'mounted': isMounted,
})}>
- {renderReporterHeader({ appState, statsStore, runnablesStore })}
+ {renderReporterHeader({ appState, statsStore, runnablesStore, spec: runnerStore.spec })}
{appState?.isPreferencesMenuOpen ? (
) : (
diff --git a/packages/reporter/src/runnables/runnable-header.tsx b/packages/reporter/src/runnables/runnable-header.tsx
index b47eac8a3a78..4d1ee230fcc6 100644
--- a/packages/reporter/src/runnables/runnable-header.tsx
+++ b/packages/reporter/src/runnables/runnable-header.tsx
@@ -4,15 +4,18 @@ import React, { ReactElement } from 'react'
import type { StatsStore } from '../header/stats-store'
import { formatDuration, getFilenameParts } from '../lib/util'
import FileNameOpener from '../lib/file-name-opener'
+import { RunnablesStore } from './runnables-store'
+import { DebugDismiss } from '../header/DebugDismiss'
const renderRunnableHeader = (children: ReactElement) => {children}
interface RunnableHeaderProps {
spec: Cypress.Cypress['spec']
statsStore: StatsStore
+ runnablesStore: RunnablesStore
}
-const RunnableHeader: React.FC = observer(({ spec, statsStore }) => {
+const RunnableHeader: React.FC = observer(({ spec, statsStore, runnablesStore }) => {
const relativeSpecPath = spec.relative
if (spec.relative === '__all') {
@@ -48,7 +51,8 @@ const RunnableHeader: React.FC = observer(({ spec, statsSto
return renderRunnableHeader(
<>
-
+
+ {runnablesStore.testFilter && runnablesStore.totalTests > 0 && }
{Boolean(statsStore.duration) && (
{formatDuration(statsStore.duration)}
)}
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 9f7351e8e947..fa0730e4a773 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -382,33 +382,6 @@
display: flex;
}
- .runnable-header {
- @include inner-header;
-
- span > span > a > svg {
- margin-bottom: -2px;
- margin-right: 8px;
- }
-
- a, a:active, a:focus, a:hover {
- color: $gray-700;
- font-weight: 300;
- strong {
- font-weight: 500;
- }
- }
-
- .duration {
- border: 1px solid $gray-900;
- border-radius: 16px;
- color: $gray-600;
- float: right;
- font-size: 12px;
- line-height: 16px;
- padding: 2px 6px;
- font-variant-numeric: tabular-nums;
- }
- }
.studio-controls {
display: none;
diff --git a/packages/reporter/src/runnables/runnables.tsx b/packages/reporter/src/runnables/runnables.tsx
index b343bc96771d..e47762a3af6b 100644
--- a/packages/reporter/src/runnables/runnables.tsx
+++ b/packages/reporter/src/runnables/runnables.tsx
@@ -6,9 +6,8 @@ import React, { MouseEvent, useCallback, useEffect, useRef } from 'react'
import events, { Events } from '../lib/events'
import { RunnablesError, RunnablesErrorModel } from './runnable-error'
import Runnable from './runnable-and-suite'
-import RunnableHeader from './runnable-header'
import type { RunnablesStore, RunnableArray } from './runnables-store'
-import statsStore, { StatsStore } from '../header/stats-store'
+import type { StatsStore } from '../header/stats-store'
import type { Scroller, UserScrollCallback } from '../lib/scroller'
import type { AppState } from '../lib/app-state'
import OpenFileInIDE from '../lib/open-file-in-ide'
@@ -48,7 +47,7 @@ const RunnablesEmptyState = ({ spec, studioEnabled, eventManager = events }: Run
No tests found.
Cypress could not detect tests in this file.
- { !isAllSpecs && (
+ {!isAllSpecs && (
<>
= observer(({ appState, scroller, erro
return (
-
Date: Fri, 6 Jun 2025 17:20:15 -0400
Subject: [PATCH 06/48] add some styles and icons to describe blocks
---
packages/reporter/src/header/header.scss | 1 +
.../src/preferences/testing-preferences.scss | 6 ++++-
.../src/runnables/runnable-and-suite.tsx | 27 ++++++++++++++++---
.../reporter/src/runnables/runnables.scss | 21 ++++++++++++---
.../reporter/src/runnables/suite-model.ts | 11 ++++++++
5 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/packages/reporter/src/header/header.scss b/packages/reporter/src/header/header.scss
index 18d18431062b..8089619c5a62 100644
--- a/packages/reporter/src/header/header.scss
+++ b/packages/reporter/src/header/header.scss
@@ -51,6 +51,7 @@ $color-transition: color 150ms ease-out;
justify-content: space-between;
padding: 20px 16px;
border: 1px solid #2E3247;
+ border-left: none;
}
.stats {
diff --git a/packages/reporter/src/preferences/testing-preferences.scss b/packages/reporter/src/preferences/testing-preferences.scss
index a6ba68c2bd80..67c3ad6219db 100644
--- a/packages/reporter/src/preferences/testing-preferences.scss
+++ b/packages/reporter/src/preferences/testing-preferences.scss
@@ -4,6 +4,10 @@
font-size: 16px;
font-weight: 400;
color: $gray-700;
+
+ &::before {
+ width: 0;
+ }
}
.testing-preference {
@@ -19,4 +23,4 @@
margin-bottom: 8px;
}
}
-}
+}
\ No newline at end of file
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index a5710ebee285..492584557d93 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -12,6 +12,7 @@ import type SuiteModel from './suite-model'
import type TestModel from '../test/test-model'
import { LaunchStudioIcon } from '../components/LaunchStudioIcon'
+import { IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped } from '@cypress-design/react-icon'
interface SuiteProps {
eventManager?: Events
@@ -28,8 +29,27 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
eventManager.emit('studio:init:suite', model.id)
}, [eventManager, model.id])
+ const getHeaderIcon = () => {
+ switch (model.state) {
+ case 'active':
+ return
+ case 'passed':
+ return
+ // TODO: secondary stroke color not working
+ case 'failed':
+ return
+ case 'pending':
+ return
+ case 'processing':
+ return
+ default:
+ return <>>
+ }
+ }
+
const _header = () => (
- <>
+
+ {getHeaderIcon()}
{model.title}
{(studioEnabled && !appState.studioActive) && (
@@ -39,14 +59,15 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
/>
)}
- >
+
)
return (
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index fa0730e4a773..af524418286b 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -104,8 +104,8 @@
}
.collapsible-header-inner {
- padding: 8px !important;
- background-color: $gray-1000;
+ padding: 8px 16px;
+ background-color: $gray-1100;
&:hover {
background-color: $gray-900;
cursor: pointer;
@@ -116,7 +116,6 @@
}
height: 100%;
- padding: 5px 15px 5px 5px;
width: 100%;
}
}
@@ -219,7 +218,23 @@
font-size: 14px;
}
+ .runnable-and-suite-header{
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ width: 100%
+ }
+
.collapsible-header-inner {
+ .collapsible-header-text {
+ display: flex;
+ width: 100%;
+ }
+
+ .runnable-title {
+ flex-grow: 1;
+ }
+
.runnable-controls-studio {
opacity: 0;
}
diff --git a/packages/reporter/src/runnables/suite-model.ts b/packages/reporter/src/runnables/suite-model.ts
index 1b9c5da79507..5ae0121897e9 100644
--- a/packages/reporter/src/runnables/suite-model.ts
+++ b/packages/reporter/src/runnables/suite-model.ts
@@ -25,10 +25,15 @@ export default class Suite extends Runnable {
_anyChildrenFailed: computed,
_allChildrenPassedOrPending: computed,
_allChildrenPending: computed,
+ _anyChildrenRunning: computed,
})
}
get state (): TestState {
+ if (this._anyChildrenRunning) {
+ return 'active'
+ }
+
if (this._anyChildrenFailed) {
return 'failed'
}
@@ -52,6 +57,12 @@ export default class Suite extends Runnable {
return _.some(this.children, (v) => v.hasRetried)
}
+ get _anyChildrenRunning () {
+ return _.some(this._childStates, (state) => {
+ return state === 'active'
+ })
+ }
+
get _anyChildrenFailed () {
return _.some(this._childStates, (state) => {
return state === 'failed'
From 8c8712580b72203b1559f63a3ead6fe5201bbb02 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 6 Jun 2025 17:42:43 -0400
Subject: [PATCH 07/48] display chevron down on describe hover
---
.../reporter/src/collapsible/collapsible.tsx | 12 ++++++++--
.../src/runnables/runnable-and-suite.tsx | 24 +++++++++++--------
2 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/packages/reporter/src/collapsible/collapsible.tsx b/packages/reporter/src/collapsible/collapsible.tsx
index 11afd208933a..22013a7e9939 100644
--- a/packages/reporter/src/collapsible/collapsible.tsx
+++ b/packages/reporter/src/collapsible/collapsible.tsx
@@ -4,11 +4,16 @@ import { onEnterOrSpace } from '../lib/util'
import ChevronIcon from '@packages/frontend-shared/src/assets/icons/chevron-down-small_x8.svg'
import DocumentBlankIcon from '@packages/frontend-shared/src/assets/icons/document-blank_x16.svg'
+export interface CollapsibleHeaderComponentProps {
+ isHovered: boolean
+}
+
interface CollapsibleProps {
isOpen?: boolean
headerClass?: string
headerStyle?: CSSProperties
header?: ReactNode
+ HeaderComponent?: React.FunctionComponent<{ isHovered: boolean }>
headerExtras?: ReactNode
containerRef?: RefObject
contentClass?: string
@@ -17,8 +22,9 @@ interface CollapsibleProps {
onOpenStateChangeRequested?: (isOpen: boolean) => void
}
-const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false, header, headerClass = '', headerStyle = {}, headerExtras, contentClass = '', hideExpander = false, containerRef = null, onOpenStateChangeRequested, children }) => {
+const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false, header, headerClass = '', headerStyle = {}, headerExtras, contentClass = '', hideExpander = false, containerRef = null, onOpenStateChangeRequested, children, HeaderComponent }) => {
const [isOpenState, setIsOpenState] = useState(isOpenAsProp)
+ const [isHovered, setIsHovered] = useState(false)
const toggleOpenState = useCallback((e?: MouseEvent) => {
e?.stopPropagation()
@@ -39,6 +45,8 @@ const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false,
className='collapsible-header'
onClick={toggleOpenState}
onKeyUp={onEnterOrSpace(toggleOpenState)}
+ onMouseEnter={() => setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
role='button'
tabIndex={0}
>
@@ -50,7 +58,7 @@ const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false,
{!hideExpander && headerClass === 'hook-header' && }
{!hideExpander && headerClass !== 'hook-header' && }
- {header}
+ {HeaderComponent ? : header}
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 492584557d93..f863fbfd3988 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -6,13 +6,13 @@ import React, { MouseEvent, useCallback } from 'react'
import appState, { AppState } from '../lib/app-state'
import events, { Events } from '../lib/events'
import Test from '../test/test'
-import Collapsible from '../collapsible/collapsible'
+import Collapsible, { CollapsibleHeaderComponentProps } from '../collapsible/collapsible'
import type SuiteModel from './suite-model'
import type TestModel from '../test/test-model'
import { LaunchStudioIcon } from '../components/LaunchStudioIcon'
-import { IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped } from '@cypress-design/react-icon'
+import { IconChevronDownMedium, IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped } from '@cypress-design/react-icon'
interface SuiteProps {
eventManager?: Events
@@ -29,27 +29,31 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
eventManager.emit('studio:init:suite', model.id)
}, [eventManager, model.id])
- const getHeaderIcon = () => {
+ const getHeaderIcon = (isHovered: boolean) => {
+ if (isHovered) {
+ return
+ }
+
switch (model.state) {
case 'active':
- return
+ return
case 'passed':
return
// TODO: secondary stroke color not working
case 'failed':
- return
+ return
case 'pending':
- return
+ return
case 'processing':
- return
+ return
default:
return <>>
}
}
- const _header = () => (
+ const HeaderComponent = ({ isHovered }: CollapsibleHeaderComponentProps) => (
- {getHeaderIcon()}
+ {getHeaderIcon(isHovered)}
{model.title}
{(studioEnabled && !appState.studioActive) && (
@@ -64,7 +68,7 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
return (
Date: Mon, 9 Jun 2025 09:47:21 -0400
Subject: [PATCH 08/48] add css for red-400
---
packages/reporter/src/runnables/runnable-and-suite.tsx | 5 ++---
packages/reporter/src/runnables/runnables.scss | 9 ++++++++-
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index f863fbfd3988..45be8d371b1d 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -29,7 +29,7 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
eventManager.emit('studio:init:suite', model.id)
}, [eventManager, model.id])
- const getHeaderIcon = (isHovered: boolean) => {
+ const getHeaderIcon = useCallback((isHovered: boolean) => {
if (isHovered) {
return
}
@@ -39,7 +39,6 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
return
case 'passed':
return
- // TODO: secondary stroke color not working
case 'failed':
return
case 'pending':
@@ -49,7 +48,7 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
default:
return <>>
}
- }
+ }, [model.state])
const HeaderComponent = ({ isHovered }: CollapsibleHeaderComponentProps) => (
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index af524418286b..7e338635797b 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -222,7 +222,14 @@
display: flex;
align-items: center;
gap: 8px;
- width: 100%
+ width: 100%;
+
+
+ .icon-dark-secondary-red-400 {
+ :nth-child(4) {
+ stroke: $red-400;
+ }
+ }
}
.collapsible-header-inner {
From 79c28a33983ececb163663e542edc0912fd360ba Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 9 Jun 2025 12:21:48 -0400
Subject: [PATCH 09/48] only display collapsible describes if there are tests
in the suite
---
.../src/runnables/runnable-and-suite.tsx | 72 ++++++++++---------
1 file changed, 40 insertions(+), 32 deletions(-)
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 45be8d371b1d..f097c6f753ab 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -50,40 +50,48 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
}
}, [model.state])
- const HeaderComponent = ({ isHovered }: CollapsibleHeaderComponentProps) => (
-
- {getHeaderIcon(isHovered)}
- {model.title}
- {(studioEnabled && !appState.studioActive) && (
-
-
-
- )}
-
- )
+ const HeaderComponent = ({ isHovered }: CollapsibleHeaderComponentProps) => {
+ return (
+
+ {getHeaderIcon(isHovered)}
+ {model.title}
+ {(studioEnabled && !appState.studioActive) && (
+
+
+
+ )}
+
+ )
+ }
+
+ let runnablesList =
+ {_.map(model.children, (runnable) => {
+ return ( )
+ })}
+
return (
-
-
- {_.map(model.children, (runnable) =>
- ( ))}
-
-
+ // we don't want to show the collapsible if there are no tests in the suite
+ model.children && !model.children.some((c) => c.type === 'test') ? runnablesList : (
+
+ {runnablesList}
+
+ )
)
})
From 195eac05c2ef51c315c6a24920a2e789f7319c69 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 9 Jun 2025 12:58:11 -0400
Subject: [PATCH 10/48] add new test on describe hover
---
.../src/runnables/runnable-and-suite.tsx | 14 ++++++-------
.../reporter/src/runnables/runnables.scss | 21 +++++++------------
2 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index f097c6f753ab..157306dc0538 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -11,8 +11,8 @@ import Collapsible, { CollapsibleHeaderComponentProps } from '../collapsible/col
import type SuiteModel from './suite-model'
import type TestModel from '../test/test-model'
-import { LaunchStudioIcon } from '../components/LaunchStudioIcon'
-import { IconChevronDownMedium, IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped } from '@cypress-design/react-icon'
+import { IconActionAddMedium, IconChevronDownMedium, IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped } from '@cypress-design/react-icon'
+import Button from '@cypress-design/react-button'
interface SuiteProps {
eventManager?: Events
@@ -56,12 +56,10 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
{getHeaderIcon(isHovered)}
{model.title}
{(studioEnabled && !appState.studioActive) && (
-
-
-
+
+
+ New Test
+
)}
)
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 7e338635797b..b0d940d9456e 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -106,11 +106,6 @@
.collapsible-header-inner {
padding: 8px 16px;
background-color: $gray-1100;
- &:hover {
- background-color: $gray-900;
- cursor: pointer;
- }
-
&:focus {
outline: 0;
}
@@ -242,17 +237,17 @@
flex-grow: 1;
}
- .runnable-controls-studio {
+ .launch-studio-button {
+ color: $gray-300;
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
opacity: 0;
}
-
+
&:hover {
- .runnable-controls-studio {
- opacity: 0.5;
-
- &:hover {
- opacity: 1;
- }
+ .launch-studio-button {
+ opacity: 1;
}
}
}
From f9a18a79330631d8ebb4a3598c442b482577cc24 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 9 Jun 2025 15:27:51 -0400
Subject: [PATCH 11/48] add describe focus styles
---
packages/reporter/src/collapsible/collapsible.tsx | 12 ++++++++++--
.../reporter/src/runnables/runnable-and-suite.tsx | 14 +++++++-------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/packages/reporter/src/collapsible/collapsible.tsx b/packages/reporter/src/collapsible/collapsible.tsx
index 22013a7e9939..5c60a369da25 100644
--- a/packages/reporter/src/collapsible/collapsible.tsx
+++ b/packages/reporter/src/collapsible/collapsible.tsx
@@ -6,6 +6,7 @@ import DocumentBlankIcon from '@packages/frontend-shared/src/assets/icons/docume
export interface CollapsibleHeaderComponentProps {
isHovered: boolean
+ isFocused: boolean
}
interface CollapsibleProps {
@@ -13,7 +14,7 @@ interface CollapsibleProps {
headerClass?: string
headerStyle?: CSSProperties
header?: ReactNode
- HeaderComponent?: React.FunctionComponent<{ isHovered: boolean }>
+ HeaderComponent?: React.FunctionComponent
headerExtras?: ReactNode
containerRef?: RefObject
contentClass?: string
@@ -25,6 +26,7 @@ interface CollapsibleProps {
const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false, header, headerClass = '', headerStyle = {}, headerExtras, contentClass = '', hideExpander = false, containerRef = null, onOpenStateChangeRequested, children, HeaderComponent }) => {
const [isOpenState, setIsOpenState] = useState(isOpenAsProp)
const [isHovered, setIsHovered] = useState(false)
+ const [isFocused, setIsFocused] = useState(false)
const toggleOpenState = useCallback((e?: MouseEvent) => {
e?.stopPropagation()
@@ -47,6 +49,12 @@ const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false,
onKeyUp={onEnterOrSpace(toggleOpenState)}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
+ onFocus={() => {
+ setIsFocused(true)
+ }}
+ onBlur={() => {
+ setIsFocused(false)
+ }}
role='button'
tabIndex={0}
>
@@ -58,7 +66,7 @@ const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false,
{!hideExpander && headerClass === 'hook-header' && }
{!hideExpander && headerClass !== 'hook-header' && }
- {HeaderComponent ? : header}
+ {HeaderComponent ? : header}
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 157306dc0538..88427401b643 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -29,9 +29,9 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
eventManager.emit('studio:init:suite', model.id)
}, [eventManager, model.id])
- const getHeaderIcon = useCallback((isHovered: boolean) => {
- if (isHovered) {
- return
+ const getHeaderIcon = useCallback((isHovered: boolean, isFocused: boolean) => {
+ if (isHovered || isFocused) {
+ return
}
switch (model.state) {
@@ -50,12 +50,12 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
}
}, [model.state])
- const HeaderComponent = ({ isHovered }: CollapsibleHeaderComponentProps) => {
+ const HeaderComponent = ({ isHovered, isFocused }: CollapsibleHeaderComponentProps) => {
return (
-
- {getHeaderIcon(isHovered)}
+
+ {getHeaderIcon(isHovered, isFocused)}
{model.title}
- {(studioEnabled && !appState.studioActive) && (
+ {(studioEnabled && !appState.studioActive && (isHovered || isFocused)) && (
New Test
From 821a452fc02cb89d04841ab4818167678b46b29e Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 9 Jun 2025 15:28:10 -0400
Subject: [PATCH 12/48] add describe focus styles scss
---
.../reporter/src/runnables/runnables.scss | 43 +++++++++++--------
1 file changed, 25 insertions(+), 18 deletions(-)
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index b0d940d9456e..92009e283608 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -96,16 +96,39 @@
padding: 0;
.collapsible-header {
- &:focus {
+ height: 36px;
+
+ &:focus-visible {
+ outline: 0;
+
.collapsible-header-inner {
- background-color: $gray-1000;
+ background-color: $gray-900;
+ outline: 0;
cursor: pointer;
+
+ .runnable-title {
+ color: $indigo-300;
+ }
+ }
+
+ .header-collapsible-indicator {
+ path {
+ stroke: $indigo-300;
+ }
+ }
+
+ .launch-studio-button {
+ border-color: $gray-900;
+ background-color: $gray-900;
}
}
.collapsible-header-inner {
padding: 8px 16px;
background-color: $gray-1100;
+ display: inline-flex;
+ align-items: center;
+
&:focus {
outline: 0;
}
@@ -242,13 +265,6 @@
display: inline-flex;
align-items: center;
gap: 4px;
- opacity: 0;
- }
-
- &:hover {
- .launch-studio-button {
- opacity: 1;
- }
}
}
}
@@ -314,10 +330,6 @@
font-size: 14px;
min-width: $reporter-contents-min-width;
white-space: pre-line;
-
- &:focus {
- outline: 1px dotted $gray-400;
- }
}
.runnable-wrapper > .collapsible-header {
@@ -325,11 +337,6 @@
position: relative;
display: inline-flex;
width: 100%;
-
- &:focus {
- outline: 1px dotted $gray-400;
- outline-offset: 3px;
- }
}
.wrap>.runnables {
From 295bf5b62cfd2b0314bd70ab6535dee32040ce4e Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 9 Jun 2025 15:30:44 -0400
Subject: [PATCH 13/48] fix add commands to test wand placement
---
packages/reporter/src/runnables/runnables.scss | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 92009e283608..c161e2652cf3 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -393,6 +393,7 @@
.collapsible-header-text {
display: flex;
+ width: 100%;
.runnable-title {
flex-grow: 1;
From dbda5e1a268f6af48e9b1ed136f034e24d862b2a Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 11 Jun 2025 11:19:21 -0400
Subject: [PATCH 14/48] update stats icon with describe and test hover and
focus
---
packages/reporter/src/header/stats.tsx | 11 +-
packages/reporter/src/lib/state-icon.tsx | 5 +-
.../src/runnables/runnable-and-suite.tsx | 8 +-
.../reporter/src/runnables/runnables.scss | 187 ++++++++++++------
4 files changed, 138 insertions(+), 73 deletions(-)
diff --git a/packages/reporter/src/header/stats.tsx b/packages/reporter/src/header/stats.tsx
index 0273fd5cf593..baed8414007c 100644
--- a/packages/reporter/src/header/stats.tsx
+++ b/packages/reporter/src/header/stats.tsx
@@ -3,10 +3,7 @@ import { observer } from 'mobx-react'
import React from 'react'
import type { StatsStore } from './stats-store'
-
-import FailedIcon from '@packages/frontend-shared/src/assets/icons/status-failed_x12.svg'
-import PassedIcon from '@packages/frontend-shared/src/assets/icons/status-passed_x12.svg'
-import PendingIcon from '@packages/frontend-shared/src/assets/icons/status-pending_x12.svg'
+import { IconStatusFailedSimple, IconStatusPassedSimple, IconStatusSkippedOutline } from '@cypress-design/react-icon'
const count = (num: number) => num > 0 ? num : '--'
@@ -17,17 +14,17 @@ interface Props {
const Stats: React.FC = observer(({ stats }: Props) => (
-
+
Passed:
{count(stats.numPassed)}
-
+
Failed:
{count(stats.numFailed)}
-
+
Pending:
{count(stats.numPending)}
diff --git a/packages/reporter/src/lib/state-icon.tsx b/packages/reporter/src/lib/state-icon.tsx
index 47b414c5d9d4..d9d5beadb614 100644
--- a/packages/reporter/src/lib/state-icon.tsx
+++ b/packages/reporter/src/lib/state-icon.tsx
@@ -8,7 +8,7 @@ import PassedIcon from '@packages/frontend-shared/src/assets/icons/status-passed
import PendingIcon from '@packages/frontend-shared/src/assets/icons/status-pending_x12.svg'
import RunningIcon from '@packages/frontend-shared/src/assets/icons/status-running_x12.svg'
import WandIcon from '@packages/frontend-shared/src/assets/icons/object-magic-wand-dark-mode_x16.svg'
-import { IconStatusQueuedOutline } from '@cypress-design/react-icon'
+import { IconStatusQueuedOutline, IconStatusSkippedOutline } from '@cypress-design/react-icon'
interface Props extends React.HTMLProps {
state: TestState
@@ -42,9 +42,10 @@ const StateIcon: React.FC = observer((props: Props) => {
)
}
+ // pending is really skipped
if (state === 'pending') {
return (
-
+
)
}
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 88427401b643..13bb53d9d2db 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -52,8 +52,10 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
const HeaderComponent = ({ isHovered, isFocused }: CollapsibleHeaderComponentProps) => {
return (
-
- {getHeaderIcon(isHovered, isFocused)}
+ <>
+
+ {getHeaderIcon(isHovered, isFocused)}
+
{model.title}
{(studioEnabled && !appState.studioActive && (isHovered || isFocused)) && (
@@ -61,7 +63,7 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
New Test
)}
-
+ >
)
}
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index c161e2652cf3..93cc3dbc067f 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -1,4 +1,17 @@
-.fa { &:not(.fa-spin) { animation: none; } }
+@mixin dotted-line {
+ content: "";
+ position: absolute;
+ left: 5.4%;
+ top: 75%;
+ height: 25%;
+ border-left: 1px dotted $gray-800;
+}
+
+.fa {
+ &:not(.fa-spin) {
+ animation: none;
+ }
+}
.reporter {
min-height: 0; // needed for firefox or else scrolling gets funky
@@ -10,14 +23,14 @@
}
.wrap {
- border-bottom: 1px solid $gray-900;
- margin-bottom: 40px;
padding-left: 0;
width: 100%;
}
.runnables {
padding-left: 0;
+ display: flex;
+ flex-direction: column;
}
.no-tests {
@@ -107,7 +120,7 @@
cursor: pointer;
.runnable-title {
- color: $indigo-300;
+ color: $indigo-300;
}
}
@@ -125,7 +138,6 @@
.collapsible-header-inner {
padding: 8px 16px;
- background-color: $gray-1100;
display: inline-flex;
align-items: center;
@@ -151,12 +163,14 @@
visibility: visible !important;
}
- .hooks-container, .runnable-err-wrapper {
+ .hooks-container,
+ .runnable-err-wrapper {
border-color: $gray-500;
}
}
- .runnable-state,.attempt-state {
+ .runnable-state,
+ .attempt-state {
display: inline-block;
line-height: 18px;
margin-right: 5px;
@@ -175,17 +189,14 @@
}
}
- &> div > .runnable-wrapper {
+ & > div > .runnable-wrapper {
border: 1px solid $gray-950;
border-radius: 4px;
border-left: 4px solid transparent;
- margin-top: 2px;
- margin-bottom: 2px;
}
&.runnable-failed > div > .runnable-wrapper,
&.runnable-failed > div > .runnable-instruments {
-
border-left: 4px solid $fail;
}
@@ -222,7 +233,11 @@
border-left: 4px solid $gray-500;
}
&.suite.runnable {
- margin-bottom: 8px;
+ margin-top: 16px;
+ }
+
+ &.suite.runnable:first-child {
+ margin-top: 4px;
}
&.suite > div > .runnable-wrapper {
@@ -230,36 +245,30 @@
margin: 0;
border-radius: 0;
background-color: $gray-1100;
-
+
+ .collapsible-header-inner {
+ background-color: $gray-1100;
+ }
+
.runnable-title {
color: $gray-400;
font-size: 14px;
}
- .runnable-and-suite-header{
+ .runnable-and-suite-header-icon {
+ position: relative;
display: flex;
align-items: center;
- gap: 8px;
- width: 100%;
-
+ justify-content: center;
+ }
- .icon-dark-secondary-red-400 {
- :nth-child(4) {
- stroke: $red-400;
- }
+ .icon-dark-secondary-red-400 {
+ :nth-child(4) {
+ stroke: $red-400;
}
}
.collapsible-header-inner {
- .collapsible-header-text {
- display: flex;
- width: 100%;
- }
-
- .runnable-title {
- flex-grow: 1;
- }
-
.launch-studio-button {
color: $gray-300;
display: inline-flex;
@@ -269,11 +278,58 @@
}
}
+ &.suite > .collapsible {
+ &.is-open > .runnable-wrapper > .collapsible-header > .collapsible-header-inner {
+ position: relative;
+
+ &::before {
+ @include dotted-line;
+ }
+ }
+ }
+
+ &.test {
+ .collapsible {
+ display: flex;
+ flex-direction: column;
+
+ .runnable-wrapper {
+ &:hover {
+ border-top: 1px solid $gray-900;
+ border-bottom: 1px solid $gray-900;
+ border-right: 1px solid $gray-900;
+
+ .collapsible-header-inner {
+ background-color: $gray-1100;
+ }
+ }
+
+ .collapsible-header {
+ &:focus-visible {
+ border-top: 1px solid $gray-800;
+ border-bottom: 1px solid $gray-800;
+ border-right: 1px solid $gray-800;
+
+ .collapsible-header-inner {
+ background-color: $gray-900;
+ }
+ }
+ }
+
+ .collapsible-header-inner {
+ background-color: $gray-1000;
+ width: 100%;
+ }
+ }
+ }
+ }
+
&.test.runnable-passed.runnable-studio {
.studio-controls {
display: flex;
- .studio-save, .studio-copy {
+ .studio-save,
+ .studio-copy {
display: block;
}
}
@@ -301,8 +357,6 @@
.runnable-state-icon {
flex-shrink: 0;
- margin-right: 5px;
- margin-top: 4px;
&.fa-spin {
.icon-light {
@@ -339,8 +393,8 @@
width: 100%;
}
- .wrap>.runnables {
- padding: 4px;
+ .wrap > .runnables {
+ padding: 0 8px;
}
.suite > div .runnable-wrapper,
@@ -351,7 +405,6 @@
}
.runnable-controls {
-
label {
padding: 2px 4px;
}
@@ -380,33 +433,41 @@
}
}
- .test.runnable-failed .runnable-controls .runnable-controls-status {
- visibility: visible;
+ // don't show the dotted line on the last test
+ // since sometimes tests are contained within a collapsible with other collapsibles
+ :nth-last-child(1 of .test) {
+ &::before {
+ content: none !important;
+ }
}
- .test .collapsible {
- display: flex;
- flex-direction: column;
-
- .runnable-wrapper .collapsible-header-inner {
- width: 100%;
-
- .collapsible-header-text {
- display: flex;
- width: 100%;
+ .runnable .test:not(.is-open) {
+ position: relative;
+ padding-bottom: 4px;
- .runnable-title {
- flex-grow: 1;
- padding-right: 10px;
- }
- }
+ &::before {
+ @include dotted-line;
}
}
+ .test.runnable-failed .runnable-controls .runnable-controls-status {
+ visibility: visible;
+ }
+
.collapsible-header {
display: flex;
}
+ .collapsible-header-text {
+ display: flex;
+ width: 100%;
+ gap: 8px;
+ align-items: center;
+
+ .runnable-title {
+ flex-grow: 1;
+ }
+ }
.studio-controls {
display: none;
@@ -447,7 +508,8 @@
font-size: 16px;
padding: 4px 10px 2px;
- &:hover, &:focus {
+ &:hover,
+ &:focus {
background-color: $indigo-100;
}
@@ -487,7 +549,7 @@
.runnable-loading {
font-family: $font-system;
-
+
.runnable-loading-animation {
display: flex;
margin: 3.5rem auto 1.5rem;
@@ -504,32 +566,35 @@
}
div:nth-child(1) {
- animation-delay:0.1s;
+ animation-delay: 0.1s;
background: $jade-400;
}
div:nth-child(2) {
- animation-delay:0.2s;
+ animation-delay: 0.2s;
background: $indigo-400;
}
div:nth-child(3) {
- animation-delay:0.3s;
+ animation-delay: 0.3s;
background: $red-400;
}
div:nth-child(4) {
- animation-delay:0.4s;
+ animation-delay: 0.4s;
background: $orange-400;
}
div:nth-child(5) {
- animation-delay:0.5s;
+ animation-delay: 0.5s;
background: $gray-400;
}
@keyframes scaling {
- 0%, 20%, 80%, 100% {
+ 0%,
+ 20%,
+ 80%,
+ 100% {
opacity: 100%;
transform: scale(0.5);
}
From 5ec13ed3d6316740a1a6259e56767b223075e6a2 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Thu, 12 Jun 2025 17:24:27 -0400
Subject: [PATCH 15/48] update test status icons
---
packages/reporter/src/lib/state-icon.tsx | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/packages/reporter/src/lib/state-icon.tsx b/packages/reporter/src/lib/state-icon.tsx
index d9d5beadb614..1da8f43ac234 100644
--- a/packages/reporter/src/lib/state-icon.tsx
+++ b/packages/reporter/src/lib/state-icon.tsx
@@ -3,12 +3,8 @@ import { observer } from 'mobx-react'
import React from 'react'
import type { TestState } from '@packages/types'
-import FailedIcon from '@packages/frontend-shared/src/assets/icons/status-failed_x12.svg'
-import PassedIcon from '@packages/frontend-shared/src/assets/icons/status-passed_x12.svg'
-import PendingIcon from '@packages/frontend-shared/src/assets/icons/status-pending_x12.svg'
-import RunningIcon from '@packages/frontend-shared/src/assets/icons/status-running_x12.svg'
import WandIcon from '@packages/frontend-shared/src/assets/icons/object-magic-wand-dark-mode_x16.svg'
-import { IconStatusQueuedOutline, IconStatusSkippedOutline } from '@cypress-design/react-icon'
+import { IconStatusFailedSimple, IconStatusPassedSimple, IconStatusQueuedOutline, IconStatusRunningOutline, IconStatusSkippedOutline } from '@cypress-design/react-icon'
interface Props extends React.HTMLProps {
state: TestState
@@ -20,13 +16,13 @@ const StateIcon: React.FC = observer((props: Props) => {
if (state === 'active') {
return (
-
+
)
}
if (state === 'failed') {
return (
-
+
)
}
@@ -38,7 +34,7 @@ const StateIcon: React.FC = observer((props: Props) => {
}
return (
-
+
)
}
@@ -49,6 +45,7 @@ const StateIcon: React.FC = observer((props: Props) => {
)
}
+ // processing is really queued
if (state === 'processing') {
return (
= observer((props: Props) => {
)
}
+ // TODO mabel i need to double check if it's this icon or the queued one
return (
-
+
)
})
From 7ae9414156d51caa2d511a61218e7ede2cdb4f2e Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Thu, 12 Jun 2025 17:26:09 -0400
Subject: [PATCH 16/48] handles some of the test body styles and states
---
packages/reporter/src/attempts/attempts.scss | 43 +++++----
packages/reporter/src/commands/commands.scss | 33 ++++---
packages/reporter/src/hooks/hooks.scss | 4 +-
.../reporter/src/instruments/instruments.scss | 4 +
.../reporter/src/runnables/runnables.scss | 93 +++++++++++++++----
5 files changed, 120 insertions(+), 57 deletions(-)
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index 92b3cc8afc25..29627d23f5de 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -10,18 +10,18 @@
}
.attempt-item {
- margin-bottom: 7px;
-
> .collapsible {
position: relative;
- margin-right: 16px;
+
.collapsible-header-inner {
outline: none;
+ display: flex;
+ align-items: center;
}
&:before {
border-left: 1px solid $gray-900;
- content: '';
+ content: "";
left: 9px;
position: absolute;
top: 22px;
@@ -47,24 +47,28 @@
}
}
- .open-close-indicator {
- svg {
- margin-right: 3px;
+ .open-close-indicator {
+ svg {
+ margin-right: 3px;
- &.collapse-icon {
- display: none;
- }
+ &.collapse-icon {
+ display: none;
+ }
- &.expand-icon {
- display: block;
+ &.expand-icon {
+ display: block;
+ }
}
}
- }
- .attempt-content {
- padding-left: 5px;
+ .attempt-content {
+ display: flex;
+
+ > div {
+ width: 100%;
+ }
+ }
}
-}
.attempt-state-failed {
.attempt-name:after {
@@ -77,7 +81,6 @@
}
}
-
.attempt-name {
display: flex;
justify-content: flex-end;
@@ -86,7 +89,7 @@
&:before {
border-top: 1px solid $gray-900;
- content: '';
+ content: "";
left: 15px;
position: absolute;
right: 0;
@@ -95,7 +98,7 @@
&:after {
color: $gray-600;
- content: '•';
+ content: "•";
left: 7px;
position: absolute;
top: 4px;
@@ -105,7 +108,7 @@
align-items: center;
border: 1px solid $gray-900;
border-radius: 7px;
- box-shadow: 0 1px 1px 0 rgba($white, 0.20);
+ box-shadow: 0 1px 1px 0 rgba($white, 0.2);
display: flex;
font-size: 12px;
padding: 2px 5px;
diff --git a/packages/reporter/src/commands/commands.scss b/packages/reporter/src/commands/commands.scss
index 290869c55e0f..cd44893e15fb 100644
--- a/packages/reporter/src/commands/commands.scss
+++ b/packages/reporter/src/commands/commands.scss
@@ -7,9 +7,11 @@
.reporter {
// rendered within ../hooks/hooks.tsx
.commands-container {
- background-color: $reporter-section-background;
min-width: $reporter-contents-min-width;
padding: 0;
+ border: 1px solid $gray-900;
+ margin: 6px;
+ border-radius: 4px;
&:empty {
display: none;
@@ -62,12 +64,12 @@
}
.command-wrapper {
- border-left: 2px solid $reporter-section-background;
- background-color: $reporter-section-background;
+ // border-left: 2px solid $reporter-section-background;
color: $gray-500;
display: flex;
min-height: 28px;
- padding-right: 2px;
+ align-items: center;
+ // gap: 24px;
&.command-is-interactive:hover {
background-color: $gray-900;
@@ -108,15 +110,15 @@
}
.command-number-column {
- @include gutter-alignment;
-
- color: #5a5f7a;
+ // @include gutter-alignment;
+ padding: 4px 24px 4px 4px;
+ color: $gray-500;
}
// when no children, add padding to act as the .command-expander-column's width
// to prevent adding another element to the page
.command-number-column + span.command-pin-target {
- margin-left: $gutter-margin;
+ // margin-left: $gutter-margin;
}
.command-pin-target.command-group {
@@ -201,12 +203,13 @@
min-width: fit-content;
}
+ // TODO mabel check these states
// Command State Styles
.command-state-passed {
- border-left: 2px solid $reporter-section-background;
+ // border-left: 2px solid $reporter-section-background;
&.command-is-interactive:hover {
- border-left: 2px solid $gray-900;
+ // border-left: 2px solid $gray-900;
}
&:not(.command-is-event) .command-number {
@@ -223,7 +226,7 @@
}
.command-state-pending {
- border-left: 2px solid $indigo-800;
+ // border-left: 2px solid $indigo-800;
background-color: $gray-900;
cursor: default;
color: $indigo-200;
@@ -270,7 +273,7 @@
color: $warn-text;
&:not(.command-type-system) {
- border-left: $warn-border;
+ // border-left: $warn-border;
}
.command-number-column,
@@ -294,7 +297,7 @@
color: $err-header-text;
&:not(.command-type-system) {
- border-left: $err-border;
+ // border-left: $err-border;
background-color: $err-header-background;
&.command-is-interactive:hover {
@@ -525,7 +528,7 @@
.command-is-pinned {
background: $indigo-1000;
- border-left: 2px solid $pinned;
+ // border-left: 2px solid $pinned;
&,
&:hover {
@@ -534,7 +537,7 @@
&:hover {
background: $indigo-900;
- border-left: 2px solid $pinned;
+ // border-left: 2px solid $pinned;
}
}
diff --git a/packages/reporter/src/hooks/hooks.scss b/packages/reporter/src/hooks/hooks.scss
index bebe1840c76f..78619bef8cb1 100644
--- a/packages/reporter/src/hooks/hooks.scss
+++ b/packages/reporter/src/hooks/hooks.scss
@@ -1,7 +1,7 @@
.reporter {
.hooks-container {
.hook-item {
- margin-bottom: 5px;
+ // margin-bottom: 5px;
&:last-of-type {
margin-bottom: 0;
@@ -29,7 +29,7 @@
flex-grow: 1;
font-size: 12px;
cursor: pointer;
- padding: 4px 0;
+ padding: 6px 0 6px 8px;
&:focus {
outline: none;
diff --git a/packages/reporter/src/instruments/instruments.scss b/packages/reporter/src/instruments/instruments.scss
index 780ac8f0e428..aae9bf5def50 100644
--- a/packages/reporter/src/instruments/instruments.scss
+++ b/packages/reporter/src/instruments/instruments.scss
@@ -10,6 +10,10 @@
padding: 0 2px 0 12px;
}
+ > .hooks-container > .hook-item > .collapsible {
+ margin-bottom: 4px;
+ }
+
.instrument-content h3,
h2,
h1:first-child {
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 93cc3dbc067f..863ab9dba969 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -105,6 +105,7 @@
padding-left: 0;
.runnable-wrapper {
+ border-radius: 4px;
border-left: 4px solid transparent;
padding: 0;
@@ -140,13 +141,12 @@
padding: 8px 16px;
display: inline-flex;
align-items: center;
+ height: 100%;
+ width: 100%;
&:focus {
outline: 0;
}
-
- height: 100%;
- width: 100%;
}
}
.runnable-controls-studio {
@@ -189,10 +189,9 @@
}
}
- & > div > .runnable-wrapper {
- border: 1px solid $gray-950;
- border-radius: 4px;
- border-left: 4px solid transparent;
+ &.runnable-processing > div > .runnable-wrapper,
+ &.runnable-processing > div > .runnable-instruments {
+ border-left: 4px solid $gray-700;
}
&.runnable-failed > div > .runnable-wrapper,
@@ -289,15 +288,41 @@
}
&.test {
+ > .collapsible {
+ &.is-open {
+ border-radius: 4px;
+ border: 3px solid #43486159;
+ background-color: $reporter-section-background;
+ }
+ }
+
.collapsible {
display: flex;
flex-direction: column;
+ &.is-open {
+ .runnable-wrapper {
+ border-bottom-left-radius: 0;
+
+ .collapsible-header {
+ border: 1px solid $gray-800;
+ }
+
+ .collapsible-header-inner {
+ background-color: $reporter-section-background;
+ }
+ }
+ }
+
.runnable-wrapper {
+ background-color: $gray-1000;
+
&:hover {
- border-top: 1px solid $gray-900;
- border-bottom: 1px solid $gray-900;
- border-right: 1px solid $gray-900;
+ .collapsible-header {
+ border-top: 1px solid $gray-900;
+ border-bottom: 1px solid $gray-900;
+ border-right: 1px solid $gray-900;
+ }
.collapsible-header-inner {
background-color: $gray-1100;
@@ -305,6 +330,11 @@
}
.collapsible-header {
+ border: 1px solid $gray-950;
+ border-radius: 4px;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+
&:focus-visible {
border-top: 1px solid $gray-800;
border-bottom: 1px solid $gray-800;
@@ -322,6 +352,31 @@
}
}
}
+ .runnable-commands-region {
+ .hooks-container {
+ display: flex;
+ gap: 4px;
+ flex-direction: column;
+ width: 100%;
+ }
+ }
+
+ &.runnable-active > .collapsible {
+ > .runnable-wrapper,
+ > .runnable-instruments {
+ border-left: 4px solid $indigo-400;
+ }
+ }
+ }
+
+ // TODO come back to these dumb dotted lines
+ &:not(.is-open) {
+ position: relative;
+ margin-bottom: 4px;
+
+ // &::before {
+ // @include dotted-line;
+ // }
}
&.test.runnable-passed.runnable-studio {
@@ -375,7 +430,7 @@
.runnable-instruments {
border-left: 4px solid transparent;
- padding-bottom: 5px;
+ padding-top: 8px;
}
.runnable-title {
@@ -441,15 +496,6 @@
}
}
- .runnable .test:not(.is-open) {
- position: relative;
- padding-bottom: 4px;
-
- &::before {
- @include dotted-line;
- }
- }
-
.test.runnable-failed .runnable-controls .runnable-controls-status {
visibility: visible;
}
@@ -590,6 +636,13 @@
background: $gray-400;
}
+ // @for $i from 1 through 5 {
+ // &:nth-child(#{$i}) {
+ // animation-delay: #{$i * 0.1}s;
+ // background: nth(($jade-400, $indigo-400, $red-400, $orange-400, $gray-400), $i);
+ // }
+ // }
+
@keyframes scaling {
0%,
20%,
From 2c9834dc18a4e775893e308e00c16d2ee01cbf98 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Thu, 12 Jun 2025 17:34:59 -0400
Subject: [PATCH 17/48] add ellipsis to runnable title and flex shrink to icons
---
packages/reporter/src/runnables/runnables.scss | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 863ab9dba969..aeb9e475737b 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -413,12 +413,6 @@
.runnable-state-icon {
flex-shrink: 0;
- &.fa-spin {
- .icon-light {
- stroke: $gray-800;
- }
- }
-
&.wand-icon {
.icon-light {
fill: $purple-300;
@@ -510,7 +504,14 @@
gap: 8px;
align-items: center;
+ svg {
+ flex-shrink: 0;
+ }
+
.runnable-title {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
flex-grow: 1;
}
}
From 250be10a89d73b4abc18d20810a33aabd3a96974 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 13 Jun 2025 12:35:43 -0400
Subject: [PATCH 18/48] fix command row stylings
---
packages/reporter/src/commands/commands.scss | 41 ++++++++-----------
packages/reporter/src/lib/mixins.scss | 12 +++---
.../reporter/src/runnables/runnables.scss | 14 +------
3 files changed, 23 insertions(+), 44 deletions(-)
diff --git a/packages/reporter/src/commands/commands.scss b/packages/reporter/src/commands/commands.scss
index cd44893e15fb..c8953ab05caf 100644
--- a/packages/reporter/src/commands/commands.scss
+++ b/packages/reporter/src/commands/commands.scss
@@ -25,7 +25,7 @@
.command-is-studio {
cursor: auto;
-
+
&.command-type-parent .commands-controls .studio-command-remove {
display: block;
padding-left: 5px;
@@ -97,12 +97,12 @@
.alias-container {
margin-left: 0;
white-space: nowrap;
-
+
> * {
display: inline-block;
margin-left: 2px;
}
-
+
> *:first-child {
margin-left: 0;
}
@@ -110,15 +110,14 @@
}
.command-number-column {
- // @include gutter-alignment;
- padding: 4px 24px 4px 4px;
+ @include gutter-alignment;
color: $gray-500;
}
// when no children, add padding to act as the .command-expander-column's width
// to prevent adding another element to the page
.command-number-column + span.command-pin-target {
- // margin-left: $gutter-margin;
+ margin-left: 24px;
}
.command-pin-target.command-group {
@@ -133,20 +132,19 @@
}
.command-group-no-children {
- padding-left: 15px;
+ padding-left: 15px;
}
.command-wrapper-text-group {
padding-left: 15px;
width: 100%;
-
}
.command-wrapper-text-group-parent {
padding-left: 5px;
}
- .nested-group-expander {
+ .nested-group-expander {
.command-expander {
position: relative;
margin-left: -16px !important; // Adjust this value to center the caret on the border
@@ -183,7 +181,7 @@
}
.fa-circle.command-message-indicator-bad {
- color: $red-500
+ color: $red-500;
}
.fa-circle.command-message-indicator-pending {
@@ -215,7 +213,7 @@
&:not(.command-is-event) .command-number {
color: $gray-700;
}
-
+
&:not(.command-is-event, .command-type-system) .command-method {
color: $gray-200;
}
@@ -238,7 +236,7 @@
.fa-circle {
line-height: 18px;
display: inline-block;
-
+
.icon-light {
stroke: $gray-800;
}
@@ -437,7 +435,7 @@
padding-top: 4px;
svg {
- color: rgba($gray-600, .25);
+ color: rgba($gray-600, 0.25);
color: $gray-600;
vertical-align: text-top;
}
@@ -456,7 +454,7 @@
display: inline-block;
margin-left: 2px;
}
-
+
> *:first-child {
margin-left: 0;
}
@@ -470,8 +468,6 @@
color: $pinned;
font-size: 12px;
line-height: 1;
- margin-top: -1px;
- margin-left: 12px;
outline: none;
text-align: right;
width: 15px;
@@ -503,16 +499,12 @@
.command-expander-column {
@extend %command-expander-base;
- padding: 4px 5px 4px 11px;
- width: 25px;
-
- .command-expander {
- margin-top: 5px;
- }
+ height: 28px;
+ width: 24px;
+ justify-content: center;
+ align-items: center;
}
-
-
.command-expander-column-group {
@extend %command-expander-base;
@include group-indent-width;
@@ -551,4 +543,3 @@
padding: 9px;
}
}
-
diff --git a/packages/reporter/src/lib/mixins.scss b/packages/reporter/src/lib/mixins.scss
index a8f51eb474f8..5c808e103ec4 100644
--- a/packages/reporter/src/lib/mixins.scss
+++ b/packages/reporter/src/lib/mixins.scss
@@ -1,7 +1,8 @@
@mixin inner-header {
background: $gray-1100;
display: block;
- font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue",
+ sans-serif;
font-size: 14px;
line-height: 24px;
overflow-wrap: break-word;
@@ -14,7 +15,7 @@
&:before,
&:after {
background-color: $gray-900;
- content: '';
+ content: "";
left: 16px;
position: absolute;
width: calc(100% - 32px);
@@ -32,11 +33,10 @@
@mixin gutter-alignment {
flex-shrink: 0;
- min-height: 1px; // because some numbers are empty
- max-height: 28px; // because some numbers are empty
+ height: 28px; // because some numbers are empty
padding-top: 4px;
padding-bottom: 4px;
- text-align: right;
+ text-align: center;
width: 24px;
}
@@ -50,4 +50,4 @@
width: 18px;
min-width: 18px;
max-width: 18px;
-}
\ No newline at end of file
+}
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index aeb9e475737b..48aefb7103c4 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -110,8 +110,6 @@
padding: 0;
.collapsible-header {
- height: 36px;
-
&:focus-visible {
outline: 0;
@@ -273,6 +271,7 @@
display: inline-flex;
align-items: center;
gap: 4px;
+ flex-shrink: 0;
}
}
}
@@ -431,7 +430,6 @@
color: $white;
font-family: $font-system;
font-size: 14px;
- min-width: $reporter-contents-min-width;
white-space: pre-line;
}
@@ -446,13 +444,6 @@
padding: 0 8px;
}
- .suite > div .runnable-wrapper,
- .test .runnable-wrapper > .collapsible-header {
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- }
-
.runnable-controls {
label {
padding: 2px 4px;
@@ -509,9 +500,6 @@
}
.runnable-title {
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
flex-grow: 1;
}
}
From 2672c3d2c17a807d32682ca2b0d9559a8e3daa6c Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 13 Jun 2025 12:41:00 -0400
Subject: [PATCH 19/48] fix session alignment
---
packages/reporter/src/lib/mixins.scss | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/packages/reporter/src/lib/mixins.scss b/packages/reporter/src/lib/mixins.scss
index 5c808e103ec4..316061712347 100644
--- a/packages/reporter/src/lib/mixins.scss
+++ b/packages/reporter/src/lib/mixins.scss
@@ -36,8 +36,11 @@
height: 28px; // because some numbers are empty
padding-top: 4px;
padding-bottom: 4px;
- text-align: center;
width: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
}
@mixin command-info-padding {
From 539f71ab9f8998810240c92cc15acaa9c989e644 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 13 Jun 2025 13:41:51 -0400
Subject: [PATCH 20/48] fix collapsible indicator styles
---
packages/reporter/src/hooks/hooks.scss | 8 +++++++-
packages/reporter/src/runnables/runnables.scss | 9 +++++----
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/packages/reporter/src/hooks/hooks.scss b/packages/reporter/src/hooks/hooks.scss
index 78619bef8cb1..3b8b60512c56 100644
--- a/packages/reporter/src/hooks/hooks.scss
+++ b/packages/reporter/src/hooks/hooks.scss
@@ -25,7 +25,8 @@
.collapsible-header {
text-transform: uppercase;
color: $gray-400;
- display: inline-block;
+ display: inline-flex;
+ align-items: center;
flex-grow: 1;
font-size: 12px;
cursor: pointer;
@@ -38,6 +39,11 @@
> .collapsible-header-inner:focus {
outline: 0;
}
+
+ .collapsible-header-inner {
+ display: flex;
+ align-items: center;
+ }
}
.hook-failed-message {
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 48aefb7103c4..879e1c78bff6 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -178,10 +178,11 @@
}
&.suite .collapsible-indicator {
- margin-left: 2px;
- // .icon-dark {
- // stroke: $gray-400;
- // }
+ flex-shrink: 0;
+
+ .icon-dark {
+ stroke: $gray-400;
+ }
.icon-light {
fill: $gray-400;
}
From b61327d5ce825dcf47565797f8f427078d6cf663 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 13 Jun 2025 19:25:59 -0400
Subject: [PATCH 21/48] handle attempt styling
---
packages/reporter/src/attempts/attempts.scss | 99 ++++++++++---------
packages/reporter/src/attempts/attempts.tsx | 8 +-
packages/reporter/src/commands/command.tsx | 26 ++---
packages/reporter/src/commands/commands.scss | 6 +-
packages/reporter/src/lib/state-icon.tsx | 31 +++---
.../reporter/src/runnables/runnables.scss | 10 +-
6 files changed, 95 insertions(+), 85 deletions(-)
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index 29627d23f5de..fd2c90c85453 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -4,11 +4,40 @@
display: none;
}
- &.has-multiple-attempts .attempt-item > .collapsible > .collapsible-header-wrapper {
- display: flex;
+ &.has-multiple-attempts .attempt-item {
+ > .collapsible > .collapsible-header-wrapper {
+ display: flex;
+ }
+
+ &:not(:first-child) {
+ > .collapsible .attempt-name:before {
+ border-left: 1px dotted $gray-800;
+ content: "";
+ left: 13px;
+ position: absolute;
+ top: 0;
+ height: 8px;
+ z-index: 1;
+ }
+ }
+ > .collapsible .attempt-name {
+ &:after {
+ border-left: 1px dotted $gray-800;
+ content: "";
+ left: 13px;
+ position: absolute;
+ bottom: 0;
+ height: 8px;
+ z-index: 1;
+ }
+ }
}
}
+ .attempt-error-region {
+ margin: 0 8px;
+ }
+
.attempt-item {
> .collapsible {
position: relative;
@@ -17,25 +46,17 @@
outline: none;
display: flex;
align-items: center;
+ width: 100%;
}
- &:before {
- border-left: 1px solid $gray-900;
- content: "";
- left: 9px;
- position: absolute;
- top: 22px;
- height: 15px;
- }
-
- &.is-open:before {
- display: none;
- }
+ // &.is-open:before {
+ // display: none;
+ // }
}
- &:last-child > .collapsible:before {
- display: none;
- }
+ // &:last-child > .collapsible:before {
+ // display: none;
+ // }
> .is-open .open-close-indicator {
svg.collapse-icon {
@@ -68,58 +89,38 @@
width: 100%;
}
}
- }
- .attempt-state-failed {
- .attempt-name:after {
- color: $fail;
- }
- }
- .attempt-state-passed {
- .attempt-name:after {
- color: $pass;
+ &:not(:last-child) .attempt-name {
+ border-bottom: 1px solid $gray-900;
}
}
.attempt-name {
display: flex;
- justify-content: flex-end;
position: relative;
width: 100%;
- &:before {
- border-top: 1px solid $gray-900;
- content: "";
- left: 15px;
- position: absolute;
- right: 0;
- top: 13px;
- }
-
- &:after {
- color: $gray-600;
- content: "•";
- left: 7px;
- position: absolute;
- top: 4px;
+ .collapsible-header {
+ width: 100%;
}
.attempt-tag {
+ display: inline-flex;
align-items: center;
- border: 1px solid $gray-900;
- border-radius: 7px;
- box-shadow: 0 1px 1px 0 rgba($white, 0.2);
- display: flex;
- font-size: 12px;
- padding: 2px 5px;
+ font-size: 14px;
+ gap: 8px;
+ width: 100%;
+ padding: 8px 10px;
position: relative;
- background-color: $black;
user-select: none;
cursor: pointer;
&:hover {
background-color: $gray-1100;
}
+ .attempt-tag-text {
+ flex-grow: 1;
+ }
}
.collapsible-more {
diff --git a/packages/reporter/src/attempts/attempts.tsx b/packages/reporter/src/attempts/attempts.tsx
index 774b0ae6892e..5156e46d4849 100644
--- a/packages/reporter/src/attempts/attempts.tsx
+++ b/packages/reporter/src/attempts/attempts.tsx
@@ -24,14 +24,16 @@ const NoCommands = () => (
)
-const AttemptHeader = ({ index, state }: {index: number, state: TestState }) => (
+const AttemptHeader = ({ index, state }: { index: number, state: TestState }) => (
+
+
+ Attempt {index + 1}
+
- Attempt {index + 1}
-
)
diff --git a/packages/reporter/src/commands/command.tsx b/packages/reporter/src/commands/command.tsx
index 83d813126a53..a10481413193 100644
--- a/packages/reporter/src/commands/command.tsx
+++ b/packages/reporter/src/commands/command.tsx
@@ -55,13 +55,13 @@ export const formattedMessage = (message: string, name?: string) => {
if (name === 'assert' && assertionArray) {
const expectedActualArray = () => {
- // get the expected and actual values of assertions
+ // get the expected and actual values of assertions
const splitTrim = message.split(assertionRegex).filter(Boolean).map((s) => s.trim())
// replace outside double asterisks with strong tags
return splitTrim.map((s) => {
- // we want to escape HTML chars so that they display
- // correctly in the command log: -> <p>
+ // we want to escape HTML chars so that they display
+ // correctly in the command log:
-> <p>
const HTMLEscapedString = mdOnlyHTML.renderInline(s)
return HTMLEscapedString.replace(asterisksRegex, `$1 `)
@@ -192,8 +192,8 @@ const Interceptions: React.FC = observer(({ interceptions, wentToOr
const interceptsTitle = (
- {wentToOrigin ? '' : <>This request did not go to origin because the response was stubbed. >}
- This request matched:
+ {wentToOrigin ? '' : <>This request did not go to origin because the response was stubbed. >}
+ This request matched:
{interceptions?.map(({ command, alias, type }, i) => (
@@ -331,7 +331,7 @@ const CommandDetails: React.FC = observer(({ model, groupId
{model.event && model.type !== 'system' ? `(${displayName(model)})` : displayName(model)}
- {!!groupId && model.type === 'system' && model.state === 'failed' && }
+ {!!groupId && model.type === 'system' && model.state === 'failed' && }
{model.referencesAlias ?
:
@@ -509,13 +509,13 @@ const Command: React.FC = observer(({ model, aliasesWithDuplicates
diff --git a/packages/reporter/src/commands/commands.scss b/packages/reporter/src/commands/commands.scss
index c8953ab05caf..f8e80c58195a 100644
--- a/packages/reporter/src/commands/commands.scss
+++ b/packages/reporter/src/commands/commands.scss
@@ -69,7 +69,6 @@
display: flex;
min-height: 28px;
align-items: center;
- // gap: 24px;
&.command-is-interactive:hover {
background-color: $gray-900;
@@ -309,10 +308,6 @@
color: $err-header-text;
}
- .failed-indicator {
- vertical-align: middle;
- }
-
.command-group {
border-color: $err-header-text;
@include nested-command-dashes($err-header-text);
@@ -541,5 +536,6 @@
box-shadow: inset 0 1px 1px rgba($white, 0.05);
min-height: 28px;
padding: 9px;
+ margin: 8px 0;
}
}
diff --git a/packages/reporter/src/lib/state-icon.tsx b/packages/reporter/src/lib/state-icon.tsx
index 1da8f43ac234..597ef39b3692 100644
--- a/packages/reporter/src/lib/state-icon.tsx
+++ b/packages/reporter/src/lib/state-icon.tsx
@@ -4,11 +4,12 @@ import React from 'react'
import type { TestState } from '@packages/types'
import WandIcon from '@packages/frontend-shared/src/assets/icons/object-magic-wand-dark-mode_x16.svg'
-import { IconStatusFailedSimple, IconStatusPassedSimple, IconStatusQueuedOutline, IconStatusRunningOutline, IconStatusSkippedOutline } from '@cypress-design/react-icon'
+import { IconStatusFailedSimple, IconStatusPassedSimple, IconStatusQueuedOutline, IconStatusQueuedSimple, IconStatusRunningOutline, IconStatusRunningSimple, IconStatusSkippedOutline, IconStatusSkippedSimple } from '@cypress-design/react-icon'
interface Props extends React.HTMLProps
{
state: TestState
isStudio?: boolean
+ iconSize?: '8' | '12' | '16'
}
const StateIcon: React.FC = observer((props: Props) => {
@@ -16,13 +17,15 @@ const StateIcon: React.FC = observer((props: Props) => {
if (state === 'active') {
return (
-
+ props.iconSize === '8' ?
+ :
+
)
}
if (state === 'failed') {
return (
-
+
)
}
@@ -34,31 +37,37 @@ const StateIcon: React.FC = observer((props: Props) => {
}
return (
-
+
)
}
// pending is really skipped
if (state === 'pending') {
return (
-
+ props.iconSize === '8' ?
+ :
+
)
}
// processing is really queued
if (state === 'processing') {
return (
-
+ props.iconSize === '8' ?
+ :
+
)
}
// TODO mabel i need to double check if it's this icon or the queued one
return (
-
+ props.iconSize === '8' ?
+ :
+
)
})
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 879e1c78bff6..c5bf3bfb51f9 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -1,7 +1,7 @@
@mixin dotted-line {
content: "";
position: absolute;
- left: 5.4%;
+ left: 4%;
top: 75%;
height: 25%;
border-left: 1px dotted $gray-800;
@@ -136,7 +136,7 @@
}
.collapsible-header-inner {
- padding: 8px 16px;
+ padding: 8px 6px;
display: inline-flex;
align-items: center;
height: 100%;
@@ -305,7 +305,7 @@
border-bottom-left-radius: 0;
.collapsible-header {
- border: 1px solid $gray-800;
+ border: 1px solid $gray-900;
}
.collapsible-header-inner {
@@ -353,6 +353,8 @@
}
}
.runnable-commands-region {
+ margin: 0 8px;
+
.hooks-container {
display: flex;
gap: 4px;
@@ -424,7 +426,7 @@
.runnable-instruments {
border-left: 4px solid transparent;
- padding-top: 8px;
+
}
.runnable-title {
From 1d071234e03e1bf5d3c969859c395ba0fbef7677 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 13 Jun 2025 19:26:12 -0400
Subject: [PATCH 22/48] fix failing tests
---
packages/reporter/cypress/e2e/tests.cy.ts | 26 +++++++++++++++++------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/packages/reporter/cypress/e2e/tests.cy.ts b/packages/reporter/cypress/e2e/tests.cy.ts
index b1ba923e33fa..934d781ba17b 100644
--- a/packages/reporter/cypress/e2e/tests.cy.ts
+++ b/packages/reporter/cypress/e2e/tests.cy.ts
@@ -48,13 +48,25 @@ describe('tests', () => {
})
it('includes the state as a class', () => {
- cy.contains('suite 1')
- .closest('.runnable')
- .should('have.class', 'runnable-failed')
+ cy.get('.suite').first().within((el) => {
+ cy.wrap(el).contains('suite 1')
+ cy.get('.test').eq(0).should('have.class', 'runnable-passed')
+ cy.get('.test').eq(1).should('have.class', 'runnable-failed')
+ })
- cy.contains('suite 2')
- .closest('.runnable')
- .should('have.class', 'runnable-passed')
+ cy.get('.suite').eq(1).within((el) => {
+ cy.wrap(el).contains('suite 1 > nested suite 1')
+ cy.get('.test').eq(0).should('have.class', 'runnable-pending')
+ cy.get('.test').eq(1).should('have.class', 'runnable-active')
+ })
+
+ cy.get('.suite').eq(2).within((el) => {
+ cy.wrap(el).contains('suite 2')
+ cy.get('.test').eq(0).should('have.class', 'runnable-passed')
+ cy.get('.test').eq(1).should('have.class', 'runnable-passed')
+ cy.get('.test').eq(2).should('have.class', 'runnable-passed')
+ .should('have.class', 'runnable-retried')
+ })
})
describe('expand and collapse', () => {
@@ -356,7 +368,7 @@ describe('studio controls', () => {
cy.contains('nested suite 1')
.parents('.collapsible').first()
.contains('test 1').click()
- .parents('.collapsible').first()
+ .parents('.collapsible').first().scrollIntoView()
.find('.studio-controls').as('pendingControls')
.should('be.visible')
From 6024731dbf10ca0dcd2a1986a5381577dbe09ef7 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 13 Jun 2025 19:42:43 -0400
Subject: [PATCH 23/48] add back command status borders
---
packages/reporter/src/commands/command.cy.tsx | 6 +++++
packages/reporter/src/commands/commands.scss | 26 ++++++++++++-------
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/packages/reporter/src/commands/command.cy.tsx b/packages/reporter/src/commands/command.cy.tsx
index 0958fc74be0b..dcc9771bf883 100644
--- a/packages/reporter/src/commands/command.cy.tsx
+++ b/packages/reporter/src/commands/command.cy.tsx
@@ -71,6 +71,10 @@ describe('commands', () => {
state: 'failed',
status: 'failed',
},
+ {
+ state: 'passed',
+ status: 'created',
+ },
]
it('session status in command', () => {
@@ -103,6 +107,8 @@ describe('commands', () => {
,
)
+ cy.get('.command-name-session').last().click()
+
cy.percySnapshot()
})
})
diff --git a/packages/reporter/src/commands/commands.scss b/packages/reporter/src/commands/commands.scss
index f8e80c58195a..bd0018b4f06e 100644
--- a/packages/reporter/src/commands/commands.scss
+++ b/packages/reporter/src/commands/commands.scss
@@ -64,7 +64,8 @@
}
.command-wrapper {
- // border-left: 2px solid $reporter-section-background;
+ border-left: 2px solid $reporter-section-background;
+ border-radius: 4px;
color: $gray-500;
display: flex;
min-height: 28px;
@@ -203,10 +204,11 @@
// TODO mabel check these states
// Command State Styles
.command-state-passed {
- // border-left: 2px solid $reporter-section-background;
+ border-left: 2px solid $reporter-section-background;
&.command-is-interactive:hover {
- // border-left: 2px solid $gray-900;
+ border-left: 2px solid $gray-900;
+ border-radius: 0 4px 4px 0;
}
&:not(.command-is-event) .command-number {
@@ -222,8 +224,10 @@
}
}
+ // pending is running in this case
.command-state-pending {
- // border-left: 2px solid $indigo-800;
+ border-left: 2px solid $indigo-800;
+ border-radius: 0 4px 4px 0;
background-color: $gray-900;
cursor: default;
color: $indigo-200;
@@ -270,7 +274,8 @@
color: $warn-text;
&:not(.command-type-system) {
- // border-left: $warn-border;
+ border-left: $warn-border;
+ border-radius: 0 4px 4px 0;
}
.command-number-column,
@@ -294,7 +299,8 @@
color: $err-header-text;
&:not(.command-type-system) {
- // border-left: $err-border;
+ border-left: $err-border;
+ border-radius: 0 4px 4px 0;
background-color: $err-header-background;
&.command-is-interactive:hover {
@@ -515,7 +521,8 @@
.command-is-pinned {
background: $indigo-1000;
- // border-left: 2px solid $pinned;
+ border-left: 2px solid $pinned;
+ border-radius: 0 4px 4px 0;
&,
&:hover {
@@ -524,7 +531,8 @@
&:hover {
background: $indigo-900;
- // border-left: 2px solid $pinned;
+ border-left: 2px solid $pinned;
+ border-radius: 0 4px 4px 0;
}
}
@@ -536,6 +544,6 @@
box-shadow: inset 0 1px 1px rgba($white, 0.05);
min-height: 28px;
padding: 9px;
- margin: 8px 0;
+ margin: 8px 0;
}
}
From 5814706cae5d7beb3baf6e964b99b7439c7b6f7f Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 16 Jun 2025 11:23:48 -0400
Subject: [PATCH 24/48] fix suites.cy.ts tests and make some styling fixes
---
packages/reporter/cypress/e2e/suites.cy.ts | 23 +++++++------------
packages/reporter/src/attempts/attempts.scss | 6 ++---
packages/reporter/src/header/header.scss | 2 +-
packages/reporter/src/hooks/hooks.scss | 2 +-
packages/reporter/src/lib/state-icon.tsx | 8 +++----
.../src/runnables/runnable-and-suite.tsx | 2 +-
.../reporter/src/runnables/runnables.scss | 1 +
7 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/packages/reporter/cypress/e2e/suites.cy.ts b/packages/reporter/cypress/e2e/suites.cy.ts
index ba91185ab3e7..4a330710e2bd 100644
--- a/packages/reporter/cypress/e2e/suites.cy.ts
+++ b/packages/reporter/cypress/e2e/suites.cy.ts
@@ -54,7 +54,11 @@ describe('suites', () => {
it('includes the state as a class', () => {
cy.contains('suite 1')
.closest('.runnable')
- .should('have.class', 'runnable-failed')
+ .should('have.class', 'runnable-active')
+
+ cy.contains('suite 1 > nested suite 1')
+ .closest('.runnable')
+ .should('have.class', 'runnable-active')
cy.contains('suite 2')
.closest('.runnable')
@@ -148,27 +152,16 @@ describe('suites', () => {
cy.contains('nested suite 1')
.closest('.runnable-wrapper')
.realHover()
- .find('.runnable-controls-studio')
+ .get('[data-cy="launch-studio-button"]')
.should('be.visible')
- .should('have.css', 'opacity', '0.5')
- })
-
- it('displays studio icon with no transparency and tooltip on hover', () => {
- cy.contains('nested suite 1')
- .closest('.collapsible-header')
- .find('.runnable-controls-studio')
- .realHover()
- .should('be.visible')
- .should('have.css', 'opacity', '1')
-
- cy.get('.cy-tooltip').contains('Add New Test')
})
it('emits studio:init:suite with the suite id when clicked', () => {
cy.stub(runner, 'emit')
cy.contains('suite 1').parents('.collapsible-header')
- .find('.runnable-controls-studio').click()
+ .realHover()
+ .get('[data-cy="launch-studio-button"]').click()
cy.wrap(runner.emit).should('be.calledWith', 'studio:init:suite', 'r2')
})
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index fd2c90c85453..e31465ffe7e3 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -13,7 +13,7 @@
> .collapsible .attempt-name:before {
border-left: 1px dotted $gray-800;
content: "";
- left: 13px;
+ left: 12px;
position: absolute;
top: 0;
height: 8px;
@@ -24,7 +24,7 @@
&:after {
border-left: 1px dotted $gray-800;
content: "";
- left: 13px;
+ left: 12px;
position: absolute;
bottom: 0;
height: 8px;
@@ -110,7 +110,7 @@
font-size: 14px;
gap: 8px;
width: 100%;
- padding: 8px 10px;
+ padding: 8px 10px 8px 9px;
position: relative;
user-select: none;
cursor: pointer;
diff --git a/packages/reporter/src/header/header.scss b/packages/reporter/src/header/header.scss
index 8089619c5a62..04b36da97b4d 100644
--- a/packages/reporter/src/header/header.scss
+++ b/packages/reporter/src/header/header.scss
@@ -60,7 +60,7 @@ $color-transition: color 150ms ease-out;
border-radius: 4px;
display: flex;
flex-wrap: wrap;
- height: 24px;
+ min-height: 24px;
justify-content: space-between;
li {
diff --git a/packages/reporter/src/hooks/hooks.scss b/packages/reporter/src/hooks/hooks.scss
index 3b8b60512c56..3611af317274 100644
--- a/packages/reporter/src/hooks/hooks.scss
+++ b/packages/reporter/src/hooks/hooks.scss
@@ -30,7 +30,7 @@
flex-grow: 1;
font-size: 12px;
cursor: pointer;
- padding: 6px 0 6px 8px;
+ padding: 6px 0 6px 2px;
&:focus {
outline: none;
diff --git a/packages/reporter/src/lib/state-icon.tsx b/packages/reporter/src/lib/state-icon.tsx
index 597ef39b3692..be1caa578f29 100644
--- a/packages/reporter/src/lib/state-icon.tsx
+++ b/packages/reporter/src/lib/state-icon.tsx
@@ -18,7 +18,7 @@ const StateIcon: React.FC = observer((props: Props) => {
if (state === 'active') {
return (
props.iconSize === '8' ?
- :
+ :
)
}
@@ -45,7 +45,7 @@ const StateIcon: React.FC = observer((props: Props) => {
if (state === 'pending') {
return (
props.iconSize === '8' ?
- :
+ :
)
}
@@ -54,7 +54,7 @@ const StateIcon: React.FC = observer((props: Props) => {
if (state === 'processing') {
return (
props.iconSize === '8' ?
- :
+ :
@@ -64,7 +64,7 @@ const StateIcon: React.FC = observer((props: Props) => {
// TODO mabel i need to double check if it's this icon or the queued one
return (
props.iconSize === '8' ?
- :
+ :
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 13bb53d9d2db..140494660133 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -58,7 +58,7 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
{model.title}
{(studioEnabled && !appState.studioActive && (isHovered || isFocused)) && (
-
+
New Test
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index c5bf3bfb51f9..8d12b1cbea9e 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -141,6 +141,7 @@
align-items: center;
height: 100%;
width: 100%;
+ min-height: 36px;
&:focus {
outline: 0;
From 2ba4f8a671a3d849025a5f54ee747dac4d228668 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 16 Jun 2025 16:00:17 -0400
Subject: [PATCH 25/48] fix styles for New test button on focused/hovered
suites
---
packages/reporter/src/header/header.scss | 1 +
.../src/runnables/runnable-and-suite.tsx | 6 ++--
.../reporter/src/runnables/runnables.scss | 30 +++++++++++++++++--
3 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/packages/reporter/src/header/header.scss b/packages/reporter/src/header/header.scss
index 04b36da97b4d..765c6e866973 100644
--- a/packages/reporter/src/header/header.scss
+++ b/packages/reporter/src/header/header.scss
@@ -14,6 +14,7 @@ $color-transition: color 150ms ease-out;
padding: 16px;
width: 100%;
z-index: 1;
+ align-items: center;
.spacer {
flex-grow: 2;
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 140494660133..55a9e7ef77c2 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -57,8 +57,10 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
{getHeaderIcon(isHovered, isFocused)}
{model.title}
- {(studioEnabled && !appState.studioActive && (isHovered || isFocused)) && (
-
+ {(studioEnabled && !appState.studioActive) && (
+
New Test
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 8d12b1cbea9e..bdf23852b36b 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -1,7 +1,7 @@
@mixin dotted-line {
content: "";
position: absolute;
- left: 4%;
+ left: 12px;
top: 75%;
height: 25%;
border-left: 1px dotted $gray-800;
@@ -136,7 +136,7 @@
}
.collapsible-header-inner {
- padding: 8px 6px;
+ padding: 8px 4px;
display: inline-flex;
align-items: center;
height: 100%;
@@ -274,6 +274,26 @@
align-items: center;
gap: 4px;
flex-shrink: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ opacity: 0;
+ background: inherit;
+
+ &.should-show {
+ opacity: 1;
+
+ &:before {
+ content: '';
+ position: absolute;
+ width: 20px;
+ left: -21px;
+ top: 0;
+ height: 100%;
+ opacity: 0.5;
+ background: inherit;
+ }
+ }
}
}
}
@@ -288,6 +308,10 @@
}
}
+ .runnable-dotted-line {
+ @include dotted-line;
+ }
+
&.test {
> .collapsible {
&.is-open {
@@ -498,6 +522,8 @@
width: 100%;
gap: 8px;
align-items: center;
+ position: relative;
+ background: inherit;
svg {
flex-shrink: 0;
From a36d24be5b83811405194bbdec53eed14df20ba8 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 16 Jun 2025 17:21:14 -0400
Subject: [PATCH 26/48] fix header test
---
packages/reporter/cypress/e2e/header.cy.ts | 2 +-
packages/reporter/src/header/header.tsx | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/reporter/cypress/e2e/header.cy.ts b/packages/reporter/cypress/e2e/header.cy.ts
index 4e4c8cc1b2d5..3bb1e9be5259 100755
--- a/packages/reporter/cypress/e2e/header.cy.ts
+++ b/packages/reporter/cypress/e2e/header.cy.ts
@@ -57,7 +57,7 @@ describe('header', () => {
})
it('shows \'Tests\' when >= 398px wide', () => {
- cy.get('.toggle-specs-wrapper span').should('be.visible')
+ cy.get('[data-cy=toggle-specs-button]').should('be.visible')
})
})
diff --git a/packages/reporter/src/header/header.tsx b/packages/reporter/src/header/header.tsx
index b7d0a574a696..34a35be56869 100644
--- a/packages/reporter/src/header/header.tsx
+++ b/packages/reporter/src/header/header.tsx
@@ -28,6 +28,7 @@ const Header: React.FC = observer(({ appState, events = def
{appState.isSpecsListOpen ? 'Collapse' : 'Expand'} Specs List F
} wrapperClassName='toggle-specs-wrapper' className='cy-tooltip'>
Date: Mon, 16 Jun 2025 17:21:35 -0400
Subject: [PATCH 27/48] attempt spacing fixes
---
packages/reporter/src/attempts/attempts.scss | 2 +-
packages/reporter/src/instruments/instruments.scss | 2 ++
packages/reporter/src/runnables/runnables.scss | 2 +-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index e31465ffe7e3..082fcc5d8e7a 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -110,7 +110,7 @@
font-size: 14px;
gap: 8px;
width: 100%;
- padding: 8px 10px 8px 9px;
+ padding: 8px 8px 8px 9px;
position: relative;
user-select: none;
cursor: pointer;
diff --git a/packages/reporter/src/instruments/instruments.scss b/packages/reporter/src/instruments/instruments.scss
index aae9bf5def50..a0404d8303e5 100644
--- a/packages/reporter/src/instruments/instruments.scss
+++ b/packages/reporter/src/instruments/instruments.scss
@@ -1,5 +1,7 @@
.reporter {
.instruments-container {
+ margin: 0 8px;
+
.instrument-content {
background-color: $reporter-section-background;
border-left: 1px solid $reporter-section-background;
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index bdf23852b36b..42fe22fcfa62 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -136,7 +136,7 @@
}
.collapsible-header-inner {
- padding: 8px 4px;
+ padding: 8px 8px 8px 6px;
display: inline-flex;
align-items: center;
height: 100%;
From d79e24f9d175f3a387d1f49c995273f5e1845d3b Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Mon, 16 Jun 2025 17:26:37 -0400
Subject: [PATCH 28/48] fix shortcuts test
---
packages/reporter/cypress/e2e/shortcuts.cy.ts | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/packages/reporter/cypress/e2e/shortcuts.cy.ts b/packages/reporter/cypress/e2e/shortcuts.cy.ts
index 4ada861cb4ff..c31c1bb7c39c 100755
--- a/packages/reporter/cypress/e2e/shortcuts.cy.ts
+++ b/packages/reporter/cypress/e2e/shortcuts.cy.ts
@@ -82,17 +82,17 @@ describe('shortcuts', function () {
cy.get('body').then(() => {
expect(runner.emit).not.to.have.been.calledWith('save:state')
- cy.contains('button', 'Specs').should('have.attr', 'aria-expanded', 'false')
+ cy.get('[data-cy=toggle-specs-button]').should('have.attr', 'aria-expanded', 'false')
})
cy.get('body').type('f').then(() => {
expect(runner.emit).to.have.been.calledWith('save:state')
- cy.contains('button', 'Specs').should('have.attr', 'aria-expanded', 'true')
+ cy.get('[data-cy=toggle-specs-button]').should('have.attr', 'aria-expanded', 'true')
})
cy.get('body').type('f').then(() => {
expect(runner.emit).to.have.been.calledWith('save:state')
- cy.contains('button', 'Specs').should('have.attr', 'aria-expanded', 'false')
+ cy.get('[data-cy=toggle-specs-button]').should('have.attr', 'aria-expanded', 'false')
})
})
@@ -140,9 +140,9 @@ describe('shortcuts', function () {
})
it('has shortcut in tooltips', () => {
- cy.get('.toggle-specs-wrapper > button').trigger('mouseover')
+ cy.get('[data-cy=toggle-specs-button]').trigger('mouseover')
cy.get('.cy-tooltip').should('have.text', 'Expand Specs List F')
- cy.get('.toggle-specs-wrapper > button').trigger('mouseout')
+ cy.get('[data-cy=toggle-specs-button]').trigger('mouseout')
cy.get('button.restart').trigger('mouseover')
cy.get('.cy-tooltip').should('have.text', 'Run All Tests R')
From 3ae4b796d168e8ac1e3fc8714ebc68117c0f2f4b Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Tue, 17 Jun 2025 11:55:56 -0400
Subject: [PATCH 29/48] add open in ide on header hover
---
.../reporter/cypress/e2e/spec_title.cy.ts | 15 ++++--
packages/reporter/src/header/header.scss | 46 +++++++++++++++++--
.../src/runnables/runnable-header.tsx | 13 +++++-
3 files changed, 62 insertions(+), 12 deletions(-)
diff --git a/packages/reporter/cypress/e2e/spec_title.cy.ts b/packages/reporter/cypress/e2e/spec_title.cy.ts
index 51f89915d69c..938c39044808 100644
--- a/packages/reporter/cypress/e2e/spec_title.cy.ts
+++ b/packages/reporter/cypress/e2e/spec_title.cy.ts
@@ -55,19 +55,24 @@ describe('spec title', () => {
})
it('displays name without path', () => {
- cy.get('.runnable-header').find('a').should('have.text', 'foo.js')
+ cy.get('.runnable-header-file-name').contains('foo.js')
cy.percySnapshot()
})
- it('displays tooltip on hover', () => {
- cy.get('.runnable-header a').first().trigger('mouseover')
- cy.get('.cy-tooltip').first().should('have.text', 'Open in IDE')
+ it('displays Open in IDE button on spec name hover', () => {
+ cy.get('.open-in-ide-button').should('have.css', 'opacity', '0')
+
+ cy.get('.runnable-header-file-name').realHover()
+ cy.get('.open-in-ide-button').should('have.css', 'opacity', '1')
+ cy.get('.open-in-ide-button').contains('Open in IDE')
+
+ cy.percySnapshot()
})
itHandlesFileOpening({
getRunner: () => runner,
- selector: '.runnable-header a',
+ selector: '.open-in-ide-button',
file: {
file: '/absolute/path/to/foo.js',
line: 0,
diff --git a/packages/reporter/src/header/header.scss b/packages/reporter/src/header/header.scss
index 765c6e866973..cd7fa10f7614 100644
--- a/packages/reporter/src/header/header.scss
+++ b/packages/reporter/src/header/header.scss
@@ -51,7 +51,7 @@ $color-transition: color 150ms ease-out;
width: 100%;
justify-content: space-between;
padding: 20px 16px;
- border: 1px solid #2E3247;
+ border: 1px solid $gray-900;
border-left: none;
}
@@ -133,16 +133,52 @@ $color-transition: color 150ms ease-out;
align-items: center;
flex: 1;
-
- >*:first-child {
+ .runnable-header-file-name {
+ display: inline-flex;
+ align-items: center;
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
+ position: relative;
+ background: $gray-1100;
+
+ .open-in-ide-button {
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ right: 0;
+ gap: 4px;
+ color: $gray-300;
+ background: inherit;
+ display: flex;
+ align-items: center;
+
+ &:before {
+ content: "";
+ position: absolute;
+ width: 22px;
+ left: -23px;
+ top: 0;
+ height: 100%;
+ opacity: 0.5;
+ background: inherit;
+ }
+
+ &:focus-visible {
+ opacity: 1;
+ }
+ }
+
+ &:hover {
+ .open-in-ide-button {
+ opacity: 1;
+ }
+ }
}
- span>span>a>svg {
+ span > span > a > svg {
margin-bottom: -2px;
margin-right: 8px;
}
@@ -180,4 +216,4 @@ $color-transition: color 150ms ease-out;
color: $gray-500;
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/reporter/src/runnables/runnable-header.tsx b/packages/reporter/src/runnables/runnable-header.tsx
index 4d1ee230fcc6..8002c74f5f67 100644
--- a/packages/reporter/src/runnables/runnable-header.tsx
+++ b/packages/reporter/src/runnables/runnable-header.tsx
@@ -3,9 +3,11 @@ import React, { ReactElement } from 'react'
import type { StatsStore } from '../header/stats-store'
import { formatDuration, getFilenameParts } from '../lib/util'
-import FileNameOpener from '../lib/file-name-opener'
import { RunnablesStore } from './runnables-store'
import { DebugDismiss } from '../header/DebugDismiss'
+import Button from '@cypress-design/react-button'
+import events from '../lib/events'
+import { IconWindowCodeEditor } from '@cypress-design/react-icon'
const renderRunnableHeader = (children: ReactElement) => {children}
@@ -49,9 +51,16 @@ const RunnableHeader: React.FC = observer(({ spec, statsSto
relativeFile: relativeSpecPath,
}
+ const openInIDE = () => {
+ return events.emit('open:file:unified', fileDetails)}> Open in IDE
+ }
+
return renderRunnableHeader(
<>
-
+
+ {fileDetails.displayFile || fileDetails.originalFile}{!!fileDetails.line && `:${fileDetails.line}`}{!!fileDetails.column && `:${fileDetails.column}`}
+ {openInIDE()}
+
{runnablesStore.testFilter && runnablesStore.totalTests > 0 && }
{Boolean(statsStore.duration) && (
{formatDuration(statsStore.duration)}
From a906916a1c6ec0ac7ec084313bc2aa70908ee33a Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Tue, 17 Jun 2025 12:11:06 -0400
Subject: [PATCH 30/48] make some styling fixes to errors
---
packages/reporter/src/errors/errors.scss | 51 ++++++++++-----------
packages/reporter/src/errors/test-error.tsx | 46 +++++++++++--------
2 files changed, 52 insertions(+), 45 deletions(-)
diff --git a/packages/reporter/src/errors/errors.scss b/packages/reporter/src/errors/errors.scss
index c9bd40049ddf..37df09fe60b3 100644
--- a/packages/reporter/src/errors/errors.scss
+++ b/packages/reporter/src/errors/errors.scss
@@ -18,7 +18,9 @@ $code-border-radius: 4px;
}
}
- p, ul, ol {
+ p,
+ ul,
+ ol {
font-size: 1.1em;
}
@@ -43,7 +45,7 @@ $code-border-radius: 4px;
}
ul li {
- list-style: disc
+ list-style: disc;
}
ol li {
@@ -59,7 +61,7 @@ $code-border-radius: 4px;
.err-group-block {
@include group-indent-width;
-
+
border-left: 1px dotted $err-header-text;
border-image-slice: 0 0 0 1;
border-image-source: repeating-linear-gradient(0deg, transparent, $err-header-text, $err-header-text 2px);
@@ -68,9 +70,8 @@ $code-border-radius: 4px;
width: 16px;
min-width: 16px;
}
- }
- }
-
+ }
+ }
.runnable-err-content {
padding: 0 12px 0 0;
@@ -80,7 +81,13 @@ $code-border-radius: 4px;
.runnable-err-content {
width: 100%;
overflow: scroll;
- padding: 0 18px;
+
+
+ .is-open {
+ > .runnable-err-stack-expander .err-collapsible-indicator {
+ transform: rotate(90deg);
+ }
+ }
}
.studio-err-wrapper {
@@ -114,14 +121,13 @@ $code-border-radius: 4px;
&.runnable-err-icon-group {
width: auto;
}
-
+
svg {
color: $red-400;
- align-self: center
+ align-self: center;
}
}
-
.runnable-err-name {
@include command-info-padding;
@@ -145,7 +151,7 @@ $code-border-radius: 4px;
font-family: $font-system;
font-size: 14px;
font-weight: 400;
- padding: 10px 0;
+ padding: 8px 14px;
code {
background-color: rgba($black, 0.2);
@@ -164,9 +170,9 @@ $code-border-radius: 4px;
.runnable-err-stack-expander {
align-items: center;
- border-top: 1px dashed rgba($red-400, 0.1);
+ border-top: 1px solid #4B364C40;
display: flex;
- padding: 10px 0;
+ padding: 16px 14px;
flex-wrap: wrap-reverse;
.collapsible-header {
flex-grow: 1;
@@ -184,10 +190,8 @@ $code-border-radius: 4px;
.collapsible-header-text {
color: $red-100;
}
- .collapsible-indicator {
- .icon-dark {
- stroke: $red-200;
- }
+ .err-collapsible-indicator path {
+ stroke: $red-200;
}
}
@@ -201,13 +205,9 @@ $code-border-radius: 4px;
color: $red-300;
font-size: 14px;
font-weight: 500;
- }
-
- .collapsible-indicator {
- line-height: 18px;
- .icon-dark {
- stroke: $red-400;
- }
+ display: inline-flex;
+ gap: 2px;
+ align-items: center;
}
}
}
@@ -264,7 +264,7 @@ $code-border-radius: 4px;
// ensure empty lines still take up vertical space
&:empty:before {
- content: ' ';
+ content: " ";
}
}
}
@@ -299,4 +299,3 @@ $code-border-radius: 4px;
}
}
}
-
diff --git a/packages/reporter/src/errors/test-error.tsx b/packages/reporter/src/errors/test-error.tsx
index a4cbb6d1224e..57acf85d2dfa 100644
--- a/packages/reporter/src/errors/test-error.tsx
+++ b/packages/reporter/src/errors/test-error.tsx
@@ -16,6 +16,7 @@ import { formattedMessage } from '../commands/command'
import WarningIcon from '@packages/frontend-shared/src/assets/icons/warning_x8.svg'
import TerminalIcon from '@packages/frontend-shared/src/assets/icons/technology-terminal_x16.svg'
+import { IconChevronRightMedium } from '@cypress-design/react-icon'
interface DocsUrlProps {
url: string | string[]
@@ -70,6 +71,12 @@ const TestError: React.FC = ({ err, groupLevel = 0, testId, comm
}
}
+ const _header =
+ <>
+
+ Stack trace
+ >
+
return (
@@ -90,25 +97,26 @@ const TestError: React.FC = ({ err, groupLevel = 0, testId, comm
{codeFrame &&
}
{err.stack &&
-
- events.emit('show:error', { err, groupLevel, testId, commandId }))}
- role='button'
- tabIndex={0}
- >
-
Print to console
-
-
- }
- contentClass='runnable-err-stack-trace'
- >
-
-
+
+ events.emit('show:error', { err, groupLevel, testId, commandId }))}
+ role='button'
+ tabIndex={0}
+ >
+
Print to console
+
+
+ }
+ contentClass='runnable-err-stack-trace'
+ >
+
+
}
From 16ff0ae8a20aa4e210f22dbcec062387a021ad8f Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Tue, 17 Jun 2025 12:41:04 -0400
Subject: [PATCH 31/48] make error styling changes
---
.../reporter/cypress/e2e/test_errors.cy.ts | 22 +++++++++----------
packages/reporter/cypress/support/utils.ts | 2 +-
packages/reporter/src/attempts/attempts.scss | 3 ++-
packages/reporter/src/commands/commands.scss | 2 +-
packages/reporter/src/hooks/hooks.scss | 8 -------
5 files changed, 15 insertions(+), 22 deletions(-)
diff --git a/packages/reporter/cypress/e2e/test_errors.cy.ts b/packages/reporter/cypress/e2e/test_errors.cy.ts
index a9f797e01e39..73770caf5d2d 100644
--- a/packages/reporter/cypress/e2e/test_errors.cy.ts
+++ b/packages/reporter/cypress/e2e/test_errors.cy.ts
@@ -70,7 +70,7 @@ describe('test errors', () => {
it('does not expand or collapse stack trace when clicking', () => {
cy.get('.runnable-err-print').click()
cy.get('.runnable-err-stack-trace').should('not.exist')
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.get('.runnable-err-stack-trace').should('be.visible')
cy.get('.runnable-err-print').click()
cy.get('.runnable-err-stack-trace').should('be.visible')
@@ -87,13 +87,13 @@ describe('test errors', () => {
})
it('opens stack trace on click', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.get('.runnable-err-stack-trace').should('be.visible')
cy.percySnapshot()
})
it('pairs down stack line whitespace', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.get('.runnable-err-stack-trace').within(() => {
cy.get('.err-stack-line')
@@ -118,7 +118,7 @@ describe('test errors', () => {
})
it('does not include message in stack trace', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.get('.runnable-err-stack-trace')
.invoke('text')
.should('not.include', 'Some Error')
@@ -126,7 +126,7 @@ describe('test errors', () => {
})
it('turns files into links', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.get('.runnable-err-stack-trace .runnable-err-file-path')
.should('have.length', 3)
@@ -141,34 +141,34 @@ describe('test errors', () => {
})
it('does not turn cypress:// files into links', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.contains('cypress://').find('a').should('not.exist')
})
it('does not turn cypress_runner.js files into links', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.contains('cypress_runner.js').find('a').should('not.exist')
})
it('does not turn lines without absoluteFile into links', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.contains('.err-stack-line', 'http://localhost:1234/me/dev/my/app.js:8:11')
.find('a').should('not.exist')
})
it('does not turn anything after "From Node.js Internals" into links', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.contains('events.js').find('a').should('not.exist')
cy.contains('node/internals.js').find('a').should('not.exist')
})
it('does not collapse test when clicking', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.get('.command-wrapper').should('be.visible')
})
it('displays tooltip on hover', () => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
cy.get('.runnable-err-stack-trace a').first().trigger('mouseover')
cy.get('.cy-tooltip').first().should('have.text', 'Open in IDE')
diff --git a/packages/reporter/cypress/support/utils.ts b/packages/reporter/cypress/support/utils.ts
index 1ac9af04decf..f4bbd0e9f96f 100644
--- a/packages/reporter/cypress/support/utils.ts
+++ b/packages/reporter/cypress/support/utils.ts
@@ -22,7 +22,7 @@ export const itHandlesFileOpening = ({ getRunner, selector, file, stackTrace = f
cy.stub(getRunner(), 'emit').callThrough()
if (stackTrace) {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
}
cy.get(selector).first().click().then(() => {
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index 082fcc5d8e7a..109ec50e148d 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -35,7 +35,7 @@
}
.attempt-error-region {
- margin: 0 8px;
+ margin: 0 8.5px;
}
.attempt-item {
@@ -84,6 +84,7 @@
.attempt-content {
display: flex;
+ margin-bottom: 6px;
> div {
width: 100%;
diff --git a/packages/reporter/src/commands/commands.scss b/packages/reporter/src/commands/commands.scss
index bd0018b4f06e..4afdc0264b75 100644
--- a/packages/reporter/src/commands/commands.scss
+++ b/packages/reporter/src/commands/commands.scss
@@ -10,7 +10,7 @@
min-width: $reporter-contents-min-width;
padding: 0;
border: 1px solid $gray-900;
- margin: 6px;
+ margin-top: 6px;
border-radius: 4px;
&:empty {
diff --git a/packages/reporter/src/hooks/hooks.scss b/packages/reporter/src/hooks/hooks.scss
index 3611af317274..5b72e0070b05 100644
--- a/packages/reporter/src/hooks/hooks.scss
+++ b/packages/reporter/src/hooks/hooks.scss
@@ -1,13 +1,5 @@
.reporter {
.hooks-container {
- .hook-item {
- // margin-bottom: 5px;
-
- &:last-of-type {
- margin-bottom: 0;
- }
- }
-
.hook-header {
font-family: $font-system;
display: flex;
From 6332f689c085ca0eca59705d85a694f83b81ba5e Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 10:49:02 -0400
Subject: [PATCH 32/48] update control icons and styles
---
packages/reporter/src/header/controls.tsx | 76 +++++++++---------
packages/reporter/src/header/header.scss | 98 ++++++++++++++++++-----
2 files changed, 116 insertions(+), 58 deletions(-)
diff --git a/packages/reporter/src/header/controls.tsx b/packages/reporter/src/header/controls.tsx
index 64736b8b48f6..8ee1cda8aff5 100755
--- a/packages/reporter/src/header/controls.tsx
+++ b/packages/reporter/src/header/controls.tsx
@@ -10,10 +10,12 @@ import type { AppState } from '../lib/app-state'
import ChevronDownIcon from '@packages/frontend-shared/src/assets/icons/chevron-down-small_x16.svg'
import ChevronUpIcon from '@packages/frontend-shared/src/assets/icons/chevron-up-small_x16.svg'
-import NextIcon from '@packages/frontend-shared/src/assets/icons/action-next_x16.svg'
-import PlayIcon from '@packages/frontend-shared/src/assets/icons/action-play_x16.svg'
-import RestartIcon from '@packages/frontend-shared/src/assets/icons/action-restart_x16.svg'
import StopIcon from '@packages/frontend-shared/src/assets/icons/action-stop_x16.svg'
+import { IconActionNext, IconActionPlayLarge, IconActionRestart } from '@cypress-design/react-icon'
+
+const iconStrokeColor = 'gray-500'
+
+const iconFillColor = 'gray-900'
const ifThen = (condition: boolean, component: React.ReactNode) => (
condition ? component : null
@@ -32,7 +34,7 @@ const Controls: React.FC = observer(({ events = defaultEvents, appState }
}
return (
-
+
Open Testing Preferences} className='cy-tooltip'>
= observer(({ events = defaultEvents, appState }
)}
- {ifThen(appState.isPaused, (
-
Resume C } className='cy-tooltip'>
-
-
-
-
- ))}
- {ifThen(appState.isRunning && !appState.isPaused, (
-
Stop Running S } className='cy-tooltip' visible={appState.studioActive ? false : null}>
-
-
-
-
- ))}
- {ifThen(!appState.isRunning, (
-
Run All Tests R } className='cy-tooltip'>
-
- {appState.studioActive ? (
-
- ) : (
-
- )}
-
-
- ))}
- {ifThen(!!appState.nextCommandName, (
-
Next [N]: {appState.nextCommandName}} className='cy-tooltip'>
-
-
-
-
- ))}
+
+ {ifThen(appState.isPaused, (
+ Resume C } className='cy-tooltip'>
+
+
+
+
+ ))}
+ {ifThen(appState.isRunning && !appState.isPaused, (
+ Stop Running S } className='cy-tooltip' visible={appState.studioActive ? false : null}>
+
+
+
+
+ ))}
+ {ifThen(!appState.isRunning, (
+ Run All Tests R } className='cy-tooltip'>
+
+ {appState.studioActive ? (
+
+ ) : (
+
+ )}
+
+
+ ))}
+ {ifThen(!!appState.nextCommandName, (
+ Next [N]: {appState.nextCommandName}} className='cy-tooltip'>
+
+
+
+
+ ))}
+
)
})
diff --git a/packages/reporter/src/header/header.scss b/packages/reporter/src/header/header.scss
index cd7fa10f7614..8bedf1b63791 100644
--- a/packages/reporter/src/header/header.scss
+++ b/packages/reporter/src/header/header.scss
@@ -50,9 +50,13 @@ $color-transition: color 150ms ease-out;
display: inline-flex;
width: 100%;
justify-content: space-between;
- padding: 20px 16px;
+ align-items: center;
+ padding: 0 16px;
border: 1px solid $gray-900;
border-left: none;
+ flex-wrap: wrap;
+ gap: 4px;
+ min-height: 64px;
}
.stats {
@@ -84,19 +88,52 @@ $color-transition: color 150ms ease-out;
}
}
- .controls {
+ @mixin control-container-styles($size) {
+ height: $size;
+
+ .testing-preferences-toggle {
+ height: $size;
+ width: $size;
+ }
+
+ .controls {
+ height: $size;
+
+ span button {
+ width: $size;
+ }
+ }
+ }
+
+ .controls-container-studio {
+ // TODO: change this to 32px for the studio redesign
+ @include control-container-styles(24px);
+ }
+
+ .controls-container {
+ @include control-container-styles(24px);
+ }
+
+ .controls-container,
+ .controls-container-studio {
+ display: inline-flex;
align-items: center;
- border: 1px solid $gray-900;
- border-radius: 4px;
- display: flex;
- flex-wrap: wrap;
justify-content: center;
- height: 24px;
+ gap: 4px;
+ flex-wrap: wrap;
+
+ span {
+ height: 100%;
+ }
.testing-preferences-toggle {
- border-left: none;
- color: $gray-700;
- margin-left: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ color: $gray-500;
+ border: 1px solid $gray-900;
+ border-radius: 4px;
&.open {
background-color: $gray-900;
@@ -104,19 +141,36 @@ $color-transition: color 150ms ease-out;
}
}
- span {
- height: 100%;
+ .controls {
+ align-items: center;
+ border: 1px solid $gray-900;
+ border-radius: 4px;
+ display: flex;
+ justify-content: center;
- button {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100%;
- color: $gray-400;
- width: 31px;
- padding: 0px;
- border-left: 1px solid $gray-900;
- margin-left: -1px;
+ span {
+ button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ color: $gray-400;
+ padding: 0px;
+ border-left: 1px solid $gray-900;
+ margin-left: -1px;
+ }
+
+ &:first-child {
+ button {
+ border-left: none;
+ }
+ }
+
+ &:last-child {
+ button {
+ border-right: none;
+ }
+ }
}
}
}
From b3065142fd4ae89579dd7c3a004564e4dcf61d29 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 11:05:29 -0400
Subject: [PATCH 33/48] fix dotted line for suites
---
packages/reporter/src/runnables/runnables.scss | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 42fe22fcfa62..0c902bb81dc3 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -1,10 +1,11 @@
@mixin dotted-line {
content: "";
position: absolute;
- left: 12px;
+ left: 14px;
top: 75%;
height: 25%;
border-left: 1px dotted $gray-800;
+ z-index: 1;
}
.fa {
From ae4d03abd03268290e3fabbf7bcc37e2607c4222 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 12:22:03 -0400
Subject: [PATCH 34/48] add test dots
---
.../src/runnables/runnable-and-suite.tsx | 17 ++++++++--
.../reporter/src/runnables/runnables.scss | 23 ++++---------
packages/reporter/src/runnables/runnables.tsx | 33 +++++++++++--------
3 files changed, 40 insertions(+), 33 deletions(-)
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 55a9e7ef77c2..4d53243f3116 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -13,6 +13,11 @@ import type TestModel from '../test/test-model'
import { IconActionAddMedium, IconChevronDownMedium, IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped } from '@cypress-design/react-icon'
import Button from '@cypress-design/react-button'
+import { RunnableArray } from './runnables-store'
+
+export const getLastTestIndex = (runnables: RunnableArray) => {
+ return [...runnables].reverse().findIndex((item) => item.type === 'test')
+}
interface SuiteProps {
eventManager?: Events
@@ -69,13 +74,16 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
)
}
+ const lastTestIndex = getLastTestIndex(model.children)
+
let runnablesList =
- {_.map(model.children, (runnable) => {
+ {_.map(model.children, (runnable, index) => {
return ( )
})}
@@ -104,14 +112,15 @@ export interface RunnableProps {
model: TestModel | SuiteModel
studioEnabled: boolean
canSaveStudioLogs: boolean
+ isLastTest: boolean
}
// NOTE: some of the driver tests dig into the React instance for this component
// in order to mess with its internal state. converting it to a functional
// component breaks that, so it needs to stay a Class-based component or
// else the driver tests need to be refactored to support it being functional
-const Runnable: React.FC = observer(({ appState: appStateProps = appState, model, studioEnabled, canSaveStudioLogs }) => {
- return (
+const Runnable: React.FC = observer(({ appState: appStateProps = appState, model, studioEnabled, canSaveStudioLogs, isLastTest }) => {
+ return (<>
= observer(({ appState: appStateProps =
canSaveStudioLogs={canSaveStudioLogs}
/>}
+ {model.type === 'test' && !isLastTest &&
}
+ >
)
})
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 0c902bb81dc3..0f1393df2db5 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -285,7 +285,7 @@
opacity: 1;
&:before {
- content: '';
+ content: "";
position: absolute;
width: 20px;
left: -21px;
@@ -309,10 +309,6 @@
}
}
- .runnable-dotted-line {
- @include dotted-line;
- }
-
&.test {
> .collapsible {
&.is-open {
@@ -397,16 +393,6 @@
}
}
- // TODO come back to these dumb dotted lines
- &:not(.is-open) {
- position: relative;
- margin-bottom: 4px;
-
- // &::before {
- // @include dotted-line;
- // }
- }
-
&.test.runnable-passed.runnable-studio {
.studio-controls {
display: flex;
@@ -450,9 +436,14 @@
}
}
+ .runnable-dotted-line {
+ margin-left: 14px;
+ height: 4px;
+ border-left: 1px dotted $gray-800;
+ }
+
.runnable-instruments {
border-left: 4px solid transparent;
-
}
.runnable-title {
diff --git a/packages/reporter/src/runnables/runnables.tsx b/packages/reporter/src/runnables/runnables.tsx
index e47762a3af6b..1cba76c393b4 100644
--- a/packages/reporter/src/runnables/runnables.tsx
+++ b/packages/reporter/src/runnables/runnables.tsx
@@ -5,7 +5,7 @@ import React, { MouseEvent, useCallback, useEffect, useRef } from 'react'
import events, { Events } from '../lib/events'
import { RunnablesError, RunnablesErrorModel } from './runnable-error'
-import Runnable from './runnable-and-suite'
+import Runnable, { getLastTestIndex } from './runnable-and-suite'
import type { RunnablesStore, RunnableArray } from './runnables-store'
import type { StatsStore } from '../header/stats-store'
import type { Scroller, UserScrollCallback } from '../lib/scroller'
@@ -90,19 +90,24 @@ interface RunnablesListProps {
canSaveStudioLogs: boolean
}
-const RunnablesList: React.FC = observer(({ runnables, studioEnabled, canSaveStudioLogs }: RunnablesListProps) => (
-
-
- {_.map(runnables, (runnable) =>
- ( ))}
-
-
-))
+const RunnablesList: React.FC = observer(({ runnables, studioEnabled, canSaveStudioLogs }: RunnablesListProps) => {
+ const lastTestIndex = getLastTestIndex(runnables)
+
+ return (
+
+
+ {_.map(runnables, (runnable, index) =>
+ ( ))}
+
+
+ )
+})
RunnablesList.displayName = 'RunnablesList'
From 01d02aa24d8753371514cf173719a9b33fe8ffd7 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 14:43:38 -0400
Subject: [PATCH 35/48] fix logic for displaying test dots
---
.../reporter/src/runnables/runnable-and-suite.tsx | 15 +++++++--------
packages/reporter/src/runnables/runnables.tsx | 6 ++----
2 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 4d53243f3116..c1e1aa7c849e 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -15,8 +15,9 @@ import { IconActionAddMedium, IconChevronDownMedium, IconObjectStackFailed, Icon
import Button from '@cypress-design/react-button'
import { RunnableArray } from './runnables-store'
-export const getLastTestIndex = (runnables: RunnableArray) => {
- return [...runnables].reverse().findIndex((item) => item.type === 'test')
+// should only show connection dots if the current runnable is a test and the next runnable is a test and is not the last runnable
+export const shouldShowConnectionDots = (runnables: RunnableArray, runnable: SuiteModel | TestModel, runnableIndex: number) => {
+ return runnable.type === 'test' && runnableIndex !== runnables.length - 1 && runnables[runnableIndex + 1].type === 'test'
}
interface SuiteProps {
@@ -74,8 +75,6 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
)
}
- const lastTestIndex = getLastTestIndex(model.children)
-
let runnablesList =
{_.map(model.children, (runnable, index) => {
return ( = observer(({ eventManager = events, model, st
model={runnable}
studioEnabled={studioEnabled}
canSaveStudioLogs={canSaveStudioLogs}
- isLastTest={lastTestIndex === index}
+ shouldShowConnectingDots={shouldShowConnectionDots(model.children, runnable, index)}
/>)
})}
@@ -112,14 +111,14 @@ export interface RunnableProps {
model: TestModel | SuiteModel
studioEnabled: boolean
canSaveStudioLogs: boolean
- isLastTest: boolean
+ shouldShowConnectingDots: boolean
}
// NOTE: some of the driver tests dig into the React instance for this component
// in order to mess with its internal state. converting it to a functional
// component breaks that, so it needs to stay a Class-based component or
// else the driver tests need to be refactored to support it being functional
-const Runnable: React.FC = observer(({ appState: appStateProps = appState, model, studioEnabled, canSaveStudioLogs, isLastTest }) => {
+const Runnable: React.FC = observer(({ appState: appStateProps = appState, model, studioEnabled, canSaveStudioLogs, shouldShowConnectingDots }) => {
return (<>
= observer(({ appState: appStateProps =
canSaveStudioLogs={canSaveStudioLogs}
/>}
- {model.type === 'test' && !isLastTest &&
}
+ {shouldShowConnectingDots &&
}
>
)
})
diff --git a/packages/reporter/src/runnables/runnables.tsx b/packages/reporter/src/runnables/runnables.tsx
index 1cba76c393b4..a8fd48652011 100644
--- a/packages/reporter/src/runnables/runnables.tsx
+++ b/packages/reporter/src/runnables/runnables.tsx
@@ -5,7 +5,7 @@ import React, { MouseEvent, useCallback, useEffect, useRef } from 'react'
import events, { Events } from '../lib/events'
import { RunnablesError, RunnablesErrorModel } from './runnable-error'
-import Runnable, { getLastTestIndex } from './runnable-and-suite'
+import Runnable, { shouldShowConnectionDots } from './runnable-and-suite'
import type { RunnablesStore, RunnableArray } from './runnables-store'
import type { StatsStore } from '../header/stats-store'
import type { Scroller, UserScrollCallback } from '../lib/scroller'
@@ -91,8 +91,6 @@ interface RunnablesListProps {
}
const RunnablesList: React.FC = observer(({ runnables, studioEnabled, canSaveStudioLogs }: RunnablesListProps) => {
- const lastTestIndex = getLastTestIndex(runnables)
-
return (
@@ -102,7 +100,7 @@ const RunnablesList: React.FC = observer(({ runnables, studi
model={runnable}
canSaveStudioLogs={canSaveStudioLogs}
studioEnabled={studioEnabled}
- isLastTest={lastTestIndex === index}
+ shouldShowConnectingDots={shouldShowConnectionDots(runnables, runnable, index)}
/>))}
From fc92577689470e72cc49725d8a526005f40e6473 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 15:41:55 -0400
Subject: [PATCH 36/48] use stop circle icon
---
packages/reporter/package.json | 2 +-
packages/reporter/src/header/controls.tsx | 5 ++--
yarn.lock | 31 ++++++++++++++++++-----
3 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/packages/reporter/package.json b/packages/reporter/package.json
index 29b760936980..88c75ca194ff 100644
--- a/packages/reporter/package.json
+++ b/packages/reporter/package.json
@@ -17,7 +17,7 @@
"devDependencies": {
"@cypress-design/constants-button": "^1.9.0",
"@cypress-design/react-button": "^1.10.1",
- "@cypress-design/react-icon": "^1.21.0",
+ "@cypress-design/react-icon": "^1.27.0",
"@cypress/react-tooltip": "0.5.3",
"@fontsource/mulish": "4.3.0",
"@fontsource/open-sans": "4.3.0",
diff --git a/packages/reporter/src/header/controls.tsx b/packages/reporter/src/header/controls.tsx
index 8ee1cda8aff5..e9aea6420e1a 100755
--- a/packages/reporter/src/header/controls.tsx
+++ b/packages/reporter/src/header/controls.tsx
@@ -10,8 +10,7 @@ import type { AppState } from '../lib/app-state'
import ChevronDownIcon from '@packages/frontend-shared/src/assets/icons/chevron-down-small_x16.svg'
import ChevronUpIcon from '@packages/frontend-shared/src/assets/icons/chevron-up-small_x16.svg'
-import StopIcon from '@packages/frontend-shared/src/assets/icons/action-stop_x16.svg'
-import { IconActionNext, IconActionPlayLarge, IconActionRestart } from '@cypress-design/react-icon'
+import { IconActionNext, IconActionPlayLarge, IconActionRestart, IconActionStopCircle } from '@cypress-design/react-icon'
const iconStrokeColor = 'gray-500'
@@ -59,7 +58,7 @@ const Controls: React.FC = observer(({ events = defaultEvents, appState }
{ifThen(appState.isRunning && !appState.isPaused, (
Stop Running S } className='cy-tooltip' visible={appState.studioActive ? false : null}>
-
+
))}
diff --git a/yarn.lock b/yarn.lock
index 4ff1954c44f5..f23034d9ce5b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2653,6 +2653,11 @@
tailwindcss "^3.4.3"
tailwindcss-hocus "^0.0.7"
+"@cypress-design/constants-button@^1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@cypress-design/constants-button/-/constants-button-1.9.0.tgz#56683bb760b7eaab9857c7f7384c5ac55eafef18"
+ integrity sha512-4mNYfEdrUJUfC4uPwr7P3u0MFsxrffvf5CefbL1HbjwxdHSLT94PhUL70kOukkN1CkM2TwPOTffNZWFLARyQeQ==
+
"@cypress-design/constants-spinner@^1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@cypress-design/constants-spinner/-/constants-spinner-1.0.1.tgz#33904995ea95c34867905aa09391d5364ffcc129"
@@ -2681,19 +2686,33 @@
tailwindcss "^3.4.3"
tailwindcss-hocus "^0.0.7"
-"@cypress-design/icon-registry@^1.0.0", "@cypress-design/icon-registry@^1.18.0", "@cypress-design/icon-registry@^1.21.0", "@cypress-design/icon-registry@^1.5.1":
+"@cypress-design/icon-registry@^1.0.0", "@cypress-design/icon-registry@^1.18.0", "@cypress-design/icon-registry@^1.5.1":
version "1.21.0"
resolved "https://registry.yarnpkg.com/@cypress-design/icon-registry/-/icon-registry-1.21.0.tgz#6f815fa1bffe40eab9507d9ec26fd9aff4a6ec62"
integrity sha512-zgbNhRCFmaby9QXpzGcT0u3ancmvPIq1bkFTSylChjgK2vvv+iQqmSnAZGrg7Zczd9McUUdTiXy0N1lzqbjAvA==
dependencies:
"@cypress-design/color-constants" "^1.1.0"
-"@cypress-design/react-icon@^1.21.0":
- version "1.21.0"
- resolved "https://registry.yarnpkg.com/@cypress-design/react-icon/-/react-icon-1.21.0.tgz#24a454692c5c6f383b8645ad4bf488412144e641"
- integrity sha512-YbEBEfmLFMO+EK5GZ10nveDQEJItAWOej5ue5Jutu9CEh3WjSCFafaFAZhBf9byOhP78UK77c4gk4b18I0nCDw==
+"@cypress-design/icon-registry@^1.27.0":
+ version "1.27.0"
+ resolved "https://registry.yarnpkg.com/@cypress-design/icon-registry/-/icon-registry-1.27.0.tgz#a657acc40cc6b43e14ebf1a0e19eb65f43e08a76"
+ integrity sha512-2/jlv/0RsCwwZpovIk8sjXsbqnnNgmpYiaQUl9XUoZ45rurhr2PuOwYk1HMAkrBcv05adzWLfiEtfzb5TwUG1w==
+ dependencies:
+ "@cypress-design/color-constants" "^1.1.0"
+
+"@cypress-design/react-button@^1.10.1":
+ version "1.10.1"
+ resolved "https://registry.yarnpkg.com/@cypress-design/react-button/-/react-button-1.10.1.tgz#31328d00789cf8a59898afdce1b71eecadec9de1"
+ integrity sha512-NFRWZRmYREaElTZj8ioyNu1lzaf0WperEw98EqC+LOYpwZzHtLahR0Ot/1DGOiCZTacrvBrtjo65VQGieXqJfQ==
+ dependencies:
+ clsx "^2.1.1"
+
+"@cypress-design/react-icon@^1.27.0":
+ version "1.27.0"
+ resolved "https://registry.yarnpkg.com/@cypress-design/react-icon/-/react-icon-1.27.0.tgz#e34952329887deb614b78b66d0357b7a4049cbe8"
+ integrity sha512-r8tu7JFwJWwsKSRMJ83ocSb6zfM0Hjnf2DTH5CEhlVxo/QHMOVk85zQSqxVHlX9p11C7jomUeMkoalD6dpKXTg==
dependencies:
- "@cypress-design/icon-registry" "^1.21.0"
+ "@cypress-design/icon-registry" "^1.27.0"
clsx "^2.1.1"
"@cypress-design/vue-button@^1.1.0", "@cypress-design/vue-button@^1.6.0":
From 826ffb1a562e9968f2db83b6c72ec1c70b84277b Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 15:42:25 -0400
Subject: [PATCH 37/48] refactor runnable and suite header icon
---
.../src/runnables/runnable-and-suite.tsx | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index c1e1aa7c849e..93c4ee81c3e1 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -11,7 +11,7 @@ import Collapsible, { CollapsibleHeaderComponentProps } from '../collapsible/col
import type SuiteModel from './suite-model'
import type TestModel from '../test/test-model'
-import { IconActionAddMedium, IconChevronDownMedium, IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped } from '@cypress-design/react-icon'
+import { IconActionAddMedium, IconChevronDownMedium, IconObjectStackFailed, IconObjectStackPassed, IconObjectStackQueued, IconObjectStackRunning, IconObjectStackSkipped, WindiColor } from '@cypress-design/react-icon'
import Button from '@cypress-design/react-button'
import { RunnableArray } from './runnables-store'
@@ -27,6 +27,11 @@ interface SuiteProps {
canSaveStudioLogs: boolean
}
+const headerIconDefaultProps = {
+ fillColor: 'gray-900' as WindiColor,
+ strokeColor: 'gray-500' as WindiColor,
+}
+
const Suite: React.FC = observer(({ eventManager = events, model, studioEnabled, canSaveStudioLogs }: SuiteProps) => {
const _launchStudio = useCallback((e: MouseEvent) => {
e.preventDefault()
@@ -42,15 +47,15 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
switch (model.state) {
case 'active':
- return
+ return
case 'passed':
- return
+ return
case 'failed':
- return
+ return
case 'pending':
- return
+ return
case 'processing':
- return
+ return
default:
return <>>
}
From d20e8967f183a04cb248c8e70b6a5dd7e4cb39d2 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 15:57:20 -0400
Subject: [PATCH 38/48] only use test children to determine current suite state
to display the suite icons
---
.../reporter/src/runnables/suite-model.ts | 46 +++++++++++--------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/packages/reporter/src/runnables/suite-model.ts b/packages/reporter/src/runnables/suite-model.ts
index 5ae0121897e9..79233646eb33 100644
--- a/packages/reporter/src/runnables/suite-model.ts
+++ b/packages/reporter/src/runnables/suite-model.ts
@@ -20,64 +20,70 @@ export default class Suite extends Runnable {
makeObservable(this, {
children: observable,
state: computed,
- _childStates: computed,
+ _testChildStates: computed,
hasRetried: computed,
- _anyChildrenFailed: computed,
- _allChildrenPassedOrPending: computed,
- _allChildrenPending: computed,
- _anyChildrenRunning: computed,
+ _anyTestChildrenFailed: computed,
+ _allTestChildrenPassedOrPending: computed,
+ _allTestChildrenPending: computed,
+ _anyTestChildrenRunning: computed,
})
}
get state (): TestState {
- if (this._anyChildrenRunning) {
+ if (this._anyTestChildrenRunning) {
return 'active'
}
- if (this._anyChildrenFailed) {
+ if (this._anyTestChildrenFailed) {
return 'failed'
}
- if (this._allChildrenPending) {
+ if (this._allTestChildrenPending) {
return 'pending'
}
- if (this._allChildrenPassedOrPending) {
+ if (this._allTestChildrenPassedOrPending) {
return 'passed'
}
return 'processing'
}
- get _childStates () {
- return _.map(this.children, 'state')
+ get _testChildStates () {
+ /**
+ * since we're displaying a collapsible for each suite whether it's a nested suite or not,
+ * we only want to consider the test children of the current suite and not the state of any suite children
+ */
+ const testChildren = this.children.filter((child) => child.type === 'test')
+
+ return _.map(testChildren, 'state')
}
get hasRetried (): boolean {
return _.some(this.children, (v) => v.hasRetried)
}
- get _anyChildrenRunning () {
- return _.some(this._childStates, (state) => {
+ get _anyTestChildrenRunning () {
+ return _.some(this._testChildStates, (state) => {
return state === 'active'
})
}
- get _anyChildrenFailed () {
- return _.some(this._childStates, (state) => {
+ get _anyTestChildrenFailed () {
+ return _.some(this._testChildStates, (state) => {
return state === 'failed'
})
}
- get _allChildrenPassedOrPending () {
- return !this._childStates.length || _.every(this._childStates, (state) => {
+ get _allTestChildrenPassedOrPending () {
+ return !this._testChildStates.length || _.every(this._testChildStates, (state) => {
return state === 'passed' || state === 'pending'
})
}
- get _allChildrenPending () {
- return !!this._childStates.length
- && _.every(this._childStates, (state) => {
+ get _allTestChildrenPending () {
+ return !!this._testChildStates.length
+ && _.every(this._testChildStates, (state) => {
return state === 'pending'
})
}
From 863df81a4c25b5fb8c4288985a565a9e06c294b9 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 16:01:20 -0400
Subject: [PATCH 39/48] fix suites test
---
packages/reporter/cypress/e2e/suites.cy.ts | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/packages/reporter/cypress/e2e/suites.cy.ts b/packages/reporter/cypress/e2e/suites.cy.ts
index 4a330710e2bd..bb0eaabd2531 100644
--- a/packages/reporter/cypress/e2e/suites.cy.ts
+++ b/packages/reporter/cypress/e2e/suites.cy.ts
@@ -54,7 +54,7 @@ describe('suites', () => {
it('includes the state as a class', () => {
cy.contains('suite 1')
.closest('.runnable')
- .should('have.class', 'runnable-active')
+ .should('have.class', 'runnable-failed')
cy.contains('suite 1 > nested suite 1')
.closest('.runnable')
@@ -160,8 +160,9 @@ describe('suites', () => {
cy.stub(runner, 'emit')
cy.contains('suite 1').parents('.collapsible-header')
- .realHover()
- .get('[data-cy="launch-studio-button"]').click()
+ .realHover().within(() => {
+ cy.get('[data-cy="launch-studio-button"]').click()
+ })
cy.wrap(runner.emit).should('be.calledWith', 'studio:init:suite', 'r2')
})
From 9b02e558b8e5eda2dc65400d9a563aef5b19c82f Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 16:14:52 -0400
Subject: [PATCH 40/48] fix suite and test icon alignments
---
packages/reporter/src/runnables/runnables.scss | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index 0f1393df2db5..a004bbd29634 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -1,7 +1,7 @@
@mixin dotted-line {
content: "";
position: absolute;
- left: 14px;
+ left: 16px;
top: 75%;
height: 25%;
border-left: 1px dotted $gray-800;
@@ -137,7 +137,6 @@
}
.collapsible-header-inner {
- padding: 8px 8px 8px 6px;
display: inline-flex;
align-items: center;
height: 100%;
@@ -247,6 +246,7 @@
background-color: $gray-1100;
.collapsible-header-inner {
+ padding: 8px;
background-color: $gray-1100;
}
@@ -316,6 +316,10 @@
border: 3px solid #43486159;
background-color: $reporter-section-background;
}
+
+ .collapsible-header-inner {
+ padding: 8px 8px 8px 4px;
+ }
}
.collapsible {
@@ -437,7 +441,7 @@
}
.runnable-dotted-line {
- margin-left: 14px;
+ margin-left: 16px;
height: 4px;
border-left: 1px dotted $gray-800;
}
From 3395dca74cf0fe2c6dcd3c3a581004f48cfd758f Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Wed, 18 Jun 2025 16:55:34 -0400
Subject: [PATCH 41/48] clean up some comments and unused variables
---
packages/reporter/src/attempts/attempts.scss | 8 --------
packages/reporter/src/collapsible/collapsible.tsx | 6 +++---
packages/reporter/src/commands/commands.scss | 1 -
packages/reporter/src/header/header.tsx | 1 -
packages/reporter/src/lib/mixins.scss | 1 -
packages/reporter/src/runnables/runnables.scss | 7 -------
packages/reporter/src/test/test.tsx | 5 ++---
7 files changed, 5 insertions(+), 24 deletions(-)
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index 109ec50e148d..70243995b679 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -48,16 +48,8 @@
align-items: center;
width: 100%;
}
-
- // &.is-open:before {
- // display: none;
- // }
}
- // &:last-child > .collapsible:before {
- // display: none;
- // }
-
> .is-open .open-close-indicator {
svg.collapse-icon {
display: block;
diff --git a/packages/reporter/src/collapsible/collapsible.tsx b/packages/reporter/src/collapsible/collapsible.tsx
index 5c60a369da25..956ae3ae67e6 100644
--- a/packages/reporter/src/collapsible/collapsible.tsx
+++ b/packages/reporter/src/collapsible/collapsible.tsx
@@ -59,12 +59,12 @@ const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false,
tabIndex={0}
>
- {!hideExpander && headerClass === 'hook-header' &&
}
- {!hideExpander && headerClass !== 'hook-header' &&
}
+ {!hideExpander && headerClass === 'hook-header' &&
}
+ {!hideExpander && headerClass !== 'hook-header' &&
}
{HeaderComponent ? : header}
diff --git a/packages/reporter/src/commands/commands.scss b/packages/reporter/src/commands/commands.scss
index 4afdc0264b75..aeaf97212443 100644
--- a/packages/reporter/src/commands/commands.scss
+++ b/packages/reporter/src/commands/commands.scss
@@ -201,7 +201,6 @@
min-width: fit-content;
}
- // TODO mabel check these states
// Command State Styles
.command-state-passed {
border-left: 2px solid $reporter-section-background;
diff --git a/packages/reporter/src/header/header.tsx b/packages/reporter/src/header/header.tsx
index 34a35be56869..7d97924865a9 100644
--- a/packages/reporter/src/header/header.tsx
+++ b/packages/reporter/src/header/header.tsx
@@ -2,7 +2,6 @@ import { observer } from 'mobx-react'
import React from 'react'
// @ts-ignore
import Tooltip from '@cypress/react-tooltip'
-// import Tooltip from '@cypress-design/react-tooltip'
import Button from '@cypress-design/react-button'
import defaultEvents, { Events } from '../lib/events'
import type { AppState } from '../lib/app-state'
diff --git a/packages/reporter/src/lib/mixins.scss b/packages/reporter/src/lib/mixins.scss
index 316061712347..a6a80ca6470a 100644
--- a/packages/reporter/src/lib/mixins.scss
+++ b/packages/reporter/src/lib/mixins.scss
@@ -40,7 +40,6 @@
display: flex;
align-items: center;
justify-content: center;
-
}
@mixin command-info-padding {
diff --git a/packages/reporter/src/runnables/runnables.scss b/packages/reporter/src/runnables/runnables.scss
index a004bbd29634..365f9632ef2f 100644
--- a/packages/reporter/src/runnables/runnables.scss
+++ b/packages/reporter/src/runnables/runnables.scss
@@ -651,13 +651,6 @@
background: $gray-400;
}
- // @for $i from 1 through 5 {
- // &:nth-child(#{$i}) {
- // animation-delay: #{$i * 0.1}s;
- // background: nth(($jade-400, $indigo-400, $red-400, $orange-400, $gray-400), $i);
- // }
- // }
-
@keyframes scaling {
0%,
20%,
diff --git a/packages/reporter/src/test/test.tsx b/packages/reporter/src/test/test.tsx
index b00deac8e759..1deb4319980e 100644
--- a/packages/reporter/src/test/test.tsx
+++ b/packages/reporter/src/test/test.tsx
@@ -161,15 +161,14 @@ const Test: React.FC
= observer(({ model, events: eventsProps = event
containerRef={containerRef}
header={_header()}
headerClass='runnable-wrapper'
- headerStyle={{ }}
contentClass='runnable-instruments'
isOpen={model.isOpen}
onOpenStateChangeRequested={(isOpen: boolean) => model.setIsOpen(isOpen)}
hideExpander
>
-
+
_scrollIntoView()} />
- {appStateProps.studioActive && }
+ {appStateProps.studioActive && }
)
From 88b3871f493b0a3a2fd655fdefff764401264222 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 20 Jun 2025 11:00:39 -0400
Subject: [PATCH 42/48] fix failing tests
---
.../app/cypress/e2e/runner/sessions.ui.cy.ts | 8 ++---
.../e2e/runner/support/verify-failures.ts | 2 +-
.../app/cypress/e2e/sidebar_navigation.cy.ts | 4 +--
packages/reporter/cypress/support/e2e.ts | 2 +-
packages/reporter/src/commands/command.tsx | 2 +-
packages/reporter/src/lib/state-icon.tsx | 34 ++++++++++---------
.../projects/e2e/cypress/support/util.js | 2 +-
7 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/packages/app/cypress/e2e/runner/sessions.ui.cy.ts b/packages/app/cypress/e2e/runner/sessions.ui.cy.ts
index d4a771e199cc..8aafd2d1f542 100644
--- a/packages/app/cypress/e2e/runner/sessions.ui.cy.ts
+++ b/packages/app/cypress/e2e/runner/sessions.ui.cy.ts
@@ -386,7 +386,7 @@ describe('runner/cypress sessions.ui.spec', {
.within(() => {
cy.contains('.command-wrapper', 'Create new session')
.should('have.class', 'command-state-failed')
- .find('.failed-indicator')
+ .find('[data-cy="failed-icon-indicator"]')
.should('exist')
})
})
@@ -465,7 +465,7 @@ describe('runner/cypress sessions.ui.spec', {
cy.contains('.command-wrapper', 'Validate session').as('validateSessionGroup')
.should('have.class', 'command-state-failed')
- .find('.failed-indicator')
+ .find('[data-cy="failed-icon-indicator"]')
.should('exist')
})
})
@@ -528,7 +528,7 @@ describe('runner/cypress sessions.ui.spec', {
cy.contains('.command-wrapper', 'Validate session').as('validateSessionGroup')
.should('have.class', 'command-state-failed')
- .find('.failed-indicator')
+ .find('[data-cy="failed-icon-indicator"]')
.should('exist')
const restoredMessagePostfix = 'This error occurred while validating the restored session. Because validation failed, we will try to recreate the session.'
@@ -545,7 +545,7 @@ describe('runner/cypress sessions.ui.spec', {
cy.contains('.command-wrapper', 'Recreate session')
.should('have.class', successfullyRecreatedSession ? 'command-state-passed' : 'command-state-failed')
- .find('.failed-indicator')
+ .find('[data-cy="failed-icon-indicator"]')
.should(successfullyRecreatedSession ? 'not.exist' : 'exist', 'is-open')
})
})
diff --git a/packages/app/cypress/e2e/runner/support/verify-failures.ts b/packages/app/cypress/e2e/runner/support/verify-failures.ts
index 425a84d72b63..a730fafbcb3d 100644
--- a/packages/app/cypress/e2e/runner/support/verify-failures.ts
+++ b/packages/app/cypress/e2e/runner/support/verify-failures.ts
@@ -71,7 +71,7 @@ const verifyFailure = (options) => {
cy.contains('.runnable-title', specTitle).closest('.runnable').as('Root')
cy.get('@Root').within(() => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
const messageLines = [].concat(message)
diff --git a/packages/app/cypress/e2e/sidebar_navigation.cy.ts b/packages/app/cypress/e2e/sidebar_navigation.cy.ts
index d6e46fdfeeae..77f0bf6ddb29 100644
--- a/packages/app/cypress/e2e/sidebar_navigation.cy.ts
+++ b/packages/app/cypress/e2e/sidebar_navigation.cy.ts
@@ -56,7 +56,7 @@ describe('Sidebar Navigation', { viewportWidth: 1280 }, () => {
cy.contains('fixture.js').click()
- cy.get('.toggle-specs-text').click()
+ cy.get('.toggle-specs-button').click()
cy.findByTestId('reporter-panel').invoke('outerWidth').then(($initialWidth) => {
expect($initialWidth).eq(100)
@@ -291,7 +291,7 @@ describe('Sidebar Navigation', { viewportWidth: 1280 }, () => {
it.skip('resize nav and persist the state after refresh', () => {
cy.contains('fixture.js').click()
- cy.get('.toggle-specs-text').click()
+ cy.get('.toggle-specs-button').click()
cy.withCtx((ctx, o) => {
o.sinon.stub(ctx.actions.localSettings, 'setPreferences').resolves()
diff --git a/packages/reporter/cypress/support/e2e.ts b/packages/reporter/cypress/support/e2e.ts
index 2119e0d339c0..be8838067354 100644
--- a/packages/reporter/cypress/support/e2e.ts
+++ b/packages/reporter/cypress/support/e2e.ts
@@ -4,7 +4,7 @@ import { installCustomPercyCommand } from '@packages/frontend-shared/cypress/sup
installCustomPercyCommand({
before () {
- cy.get('.toggle-specs-text').should('be.visible')
+ cy.get('.toggle-specs-button').should('be.visible')
},
elementOverrides: {
'.command-progress': true,
diff --git a/packages/reporter/src/commands/command.tsx b/packages/reporter/src/commands/command.tsx
index a10481413193..819102f60fce 100644
--- a/packages/reporter/src/commands/command.tsx
+++ b/packages/reporter/src/commands/command.tsx
@@ -331,7 +331,7 @@ const CommandDetails: React.FC = observer(({ model, groupId
{model.event && model.type !== 'system' ? `(${displayName(model)})` : displayName(model)}
- {!!groupId && model.type === 'system' && model.state === 'failed' && }
+ {!!groupId && model.type === 'system' && model.state === 'failed' && }
{model.referencesAlias ?
:
diff --git a/packages/reporter/src/lib/state-icon.tsx b/packages/reporter/src/lib/state-icon.tsx
index be1caa578f29..927e6d9bb436 100644
--- a/packages/reporter/src/lib/state-icon.tsx
+++ b/packages/reporter/src/lib/state-icon.tsx
@@ -6,26 +6,26 @@ import type { TestState } from '@packages/types'
import WandIcon from '@packages/frontend-shared/src/assets/icons/object-magic-wand-dark-mode_x16.svg'
import { IconStatusFailedSimple, IconStatusPassedSimple, IconStatusQueuedOutline, IconStatusQueuedSimple, IconStatusRunningOutline, IconStatusRunningSimple, IconStatusSkippedOutline, IconStatusSkippedSimple } from '@cypress-design/react-icon'
-interface Props extends React.HTMLProps {
+interface Props extends React.SVGProps {
state: TestState
isStudio?: boolean
iconSize?: '8' | '12' | '16'
}
const StateIcon: React.FC = observer((props: Props) => {
- const { state, isStudio, ...rest } = props
+ const { state, isStudio, ref, iconSize, ...rest } = props
if (state === 'active') {
return (
- props.iconSize === '8' ?
- :
-
+ iconSize === '8' ?
+ :
+
)
}
if (state === 'failed') {
return (
-
+
)
}
@@ -37,36 +37,38 @@ const StateIcon: React.FC = observer((props: Props) => {
}
return (
-
+
)
}
// pending is really skipped
if (state === 'pending') {
return (
- props.iconSize === '8' ?
- :
-
+ iconSize === '8' ?
+ :
+
)
}
// processing is really queued
if (state === 'processing') {
return (
- props.iconSize === '8' ?
- :
+ iconSize === '8' ?
+ :
)
}
// TODO mabel i need to double check if it's this icon or the queued one
return (
- props.iconSize === '8' ?
- :
+ iconSize === '8' ?
+ :
)
})
diff --git a/system-tests/projects/e2e/cypress/support/util.js b/system-tests/projects/e2e/cypress/support/util.js
index 1ab07814d030..c608d5337b31 100644
--- a/system-tests/projects/e2e/cypress/support/util.js
+++ b/system-tests/projects/e2e/cypress/support/util.js
@@ -37,7 +37,7 @@ export const verify = (title, ctx, options) => {
.contains(`FAIL - ${getTitle(title, ctx)}`)
.closest('.collapsible')
.within(() => {
- cy.contains('View stack trace').click()
+ cy.contains('Stack trace').click()
_.each([].concat(message), (msg) => {
cy.get('.runnable-err-message')
From e55e8cefbddb58dac620a278e802bc79380306ea Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 20 Jun 2025 11:30:57 -0400
Subject: [PATCH 43/48] fix failing studio tests
---
packages/app/cypress/e2e/studio/helper.ts | 10 +++++++---
packages/reporter/cypress/e2e/suites.cy.ts | 4 ++--
packages/reporter/src/runnables/runnable-and-suite.tsx | 2 +-
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/packages/app/cypress/e2e/studio/helper.ts b/packages/app/cypress/e2e/studio/helper.ts
index 6c66f9dbf475..34a9c03e5f71 100644
--- a/packages/app/cypress/e2e/studio/helper.ts
+++ b/packages/app/cypress/e2e/studio/helper.ts
@@ -30,9 +30,13 @@ export function launchStudio ({ specName = 'spec.cy.js', createNewTest = false,
.closest('.runnable-wrapper').as('runnable-wrapper')
.realHover()
- cy.get('@runnable-wrapper')
- .findByTestId('launch-studio')
- .click()
+ if (createNewTest) {
+ cy.get('@runnable-wrapper').realHover().findByTestId('create-new-test-button').click()
+ } else {
+ cy.get('@runnable-wrapper')
+ .findByTestId('launch-studio')
+ .click()
+ }
// Studio re-executes spec before waiting for commands - wait for the spec to finish executing.
cy.waitForSpecToFinish()
diff --git a/packages/reporter/cypress/e2e/suites.cy.ts b/packages/reporter/cypress/e2e/suites.cy.ts
index bb0eaabd2531..4121dcf28705 100644
--- a/packages/reporter/cypress/e2e/suites.cy.ts
+++ b/packages/reporter/cypress/e2e/suites.cy.ts
@@ -152,7 +152,7 @@ describe('suites', () => {
cy.contains('nested suite 1')
.closest('.runnable-wrapper')
.realHover()
- .get('[data-cy="launch-studio-button"]')
+ .get('[data-cy="create-new-test-button"]')
.should('be.visible')
})
@@ -161,7 +161,7 @@ describe('suites', () => {
cy.contains('suite 1').parents('.collapsible-header')
.realHover().within(() => {
- cy.get('[data-cy="launch-studio-button"]').click()
+ cy.get('[data-cy="create-new-test-button"]').click()
})
cy.wrap(runner.emit).should('be.calledWith', 'studio:init:suite', 'r2')
diff --git a/packages/reporter/src/runnables/runnable-and-suite.tsx b/packages/reporter/src/runnables/runnable-and-suite.tsx
index 93c4ee81c3e1..08a371218622 100644
--- a/packages/reporter/src/runnables/runnable-and-suite.tsx
+++ b/packages/reporter/src/runnables/runnable-and-suite.tsx
@@ -69,7 +69,7 @@ const Suite: React.FC = observer(({ eventManager = events, model, st
{model.title}
{(studioEnabled && !appState.studioActive) && (
-
From df3098f521d5e78b96cae89e176dcdd0f277bb78 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 20 Jun 2025 14:20:43 -0400
Subject: [PATCH 44/48] fix failing tests
---
.../cypress/e2e/runner/support/spec-loader.ts | 7 +++---
packages/driver/cypress/support/utils.ts | 2 +-
packages/reporter/cypress/e2e/commands.cy.ts | 24 +++++++++++++++----
packages/reporter/cypress/e2e/runnables.cy.ts | 9 +++----
4 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/packages/app/cypress/e2e/runner/support/spec-loader.ts b/packages/app/cypress/e2e/runner/support/spec-loader.ts
index 651a6a611153..94182aff830e 100644
--- a/packages/app/cypress/e2e/runner/support/spec-loader.ts
+++ b/packages/app/cypress/e2e/runner/support/spec-loader.ts
@@ -5,9 +5,10 @@ export const shouldHaveTestResults = ({ passCount, failCount, pendingCount }) =>
failCount = failCount || '--'
cy.get('button.restart', { timeout: 30000 }).should('be.visible') // ensure tests are finished running
- cy.findByLabelText('Stats', { timeout: 10000 }).within(() => {
- cy.get('.passed .num', { timeout: 30000 }).should('have.text', `${passCount}`)
- cy.get('.failed .num', { timeout: 30000 }).should('have.text', `${failCount}`)
+
+ cy.get('.stats', { timeout: 10000 }).within(() => {
+ cy.get('.passed .num', { timeout: 40000 }).should('have.text', `${passCount}`)
+ cy.get('.failed .num', { timeout: 40000 }).should('have.text', `${failCount}`)
if (pendingCount) {
cy.get('.pending .num', { timeout: 20000 }).should('have.text', `${pendingCount}`)
diff --git a/packages/driver/cypress/support/utils.ts b/packages/driver/cypress/support/utils.ts
index 486f2dd40e4e..08ef205d357b 100644
--- a/packages/driver/cypress/support/utils.ts
+++ b/packages/driver/cypress/support/utils.ts
@@ -9,7 +9,7 @@ export const getCommandLogWithText = (command, type?) => {
cy.$$('.runnable-active .collapsible:not(.is-open) .collapsible-header', top?.document).click()
return cy
- .$$(`.runnable-active .command-${type}:contains(${command})`, top?.document)
+ .$$(`.test.runnable-active .command-${type}:contains(${command})`, top?.document)
.closest('.command')
}
diff --git a/packages/reporter/cypress/e2e/commands.cy.ts b/packages/reporter/cypress/e2e/commands.cy.ts
index ce0267afb0ad..86f5ef0544d0 100644
--- a/packages/reporter/cypress/e2e/commands.cy.ts
+++ b/packages/reporter/cypress/e2e/commands.cy.ts
@@ -898,7 +898,10 @@ describe('commands', { viewportHeight: 1000 }, () => {
})
it('shows a tooltip', () => {
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
cy.get('.cy-tooltip').should('have.text', 'Printed output to your console')
})
@@ -911,21 +914,32 @@ describe('commands', { viewportHeight: 1000 }, () => {
it('prints to console', () => {
cy.spy(runner, 'emit')
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
cy.wrap(runner.emit).should('be.calledWith', 'runner:console:log', 'r3', fakeIdForTest)
})
it('shows the snapshot', () => {
cy.spy(runner, 'emit')
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
cy.wrap(runner.emit).should('be.calledWith', 'runner:show:snapshot', 'r3', fakeIdForTest)
})
it('unpins after clicking again, does not re-print to the console', () => {
cy.spy(runner, 'emit')
- cy.get('.command-name-within').click('top')
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
// @ts-ignore
cy.wrap(runner.emit.withArgs('runner:console:log')).should('be.calledOnce')
})
diff --git a/packages/reporter/cypress/e2e/runnables.cy.ts b/packages/reporter/cypress/e2e/runnables.cy.ts
index eb108faa239d..966b8cd653d1 100644
--- a/packages/reporter/cypress/e2e/runnables.cy.ts
+++ b/packages/reporter/cypress/e2e/runnables.cy.ts
@@ -137,8 +137,8 @@ describe('runnables', () => {
it('does not display time if no time taken', () => {
start()
- cy.get('.runnable-header span:first').should('have.text', 'foo.js')
- cy.get('.runnable-header span:last').should('not.have.text', '--')
+ cy.get('.runnable-header .runnable-header-file-name').contains('foo.js')
+ cy.get('.runnable-header .duration').should('not.exist')
})
describe('when there are no tests', () => {
@@ -204,11 +204,12 @@ describe('runnables', () => {
})
it('contains name of spec and emits when clicked', () => {
- const selector = '.runnable-header a'
+ const selector = '.runnable-header-file-name'
cy.stub(runner, 'emit').callThrough()
- cy.get(selector).as('spec-title').contains('foo.js')
+ cy.get(selector).as('spec-title').contains('foo.js').realHover()
+ cy.get('.open-in-ide-button').click()
cy.get(selector).click().then(() => {
expect(runner.emit).to.be.calledWith('open:file:unified')
})
From 87ea168f76aeabd513f34d121096dcf5e93a3f8c Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 20 Jun 2025 14:45:53 -0400
Subject: [PATCH 45/48] fix meta test
---
packages/reporter/cypress/e2e/meta_&%.cy.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/reporter/cypress/e2e/meta_&%.cy.ts b/packages/reporter/cypress/e2e/meta_&%.cy.ts
index 9afdea03c851..0f424b0cbc2c 100644
--- a/packages/reporter/cypress/e2e/meta_&%.cy.ts
+++ b/packages/reporter/cypress/e2e/meta_&%.cy.ts
@@ -3,7 +3,7 @@
describe('special characters', () => {
it('displays file name with decoded special characters', () => {
cy.wrap(Cypress.$(window.top.document.body))
- .find('.reporter .runnable-header a')
- .should('have.text', 'meta_&%.cy.ts')
+ .find('.reporter .runnable-header')
+ .contains('meta_&%.cy.ts')
})
})
From ed6e5202a337a339cb5794a4f0dd47f1e27f6b46 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 20 Jun 2025 14:54:16 -0400
Subject: [PATCH 46/48] fix suite_model test
---
packages/reporter/cypress/e2e/unit/suite_model.cy.ts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/packages/reporter/cypress/e2e/unit/suite_model.cy.ts b/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
index 8822c98e1dcd..1c645a5227a2 100644
--- a/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
+++ b/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
@@ -4,7 +4,7 @@ import TestModel from '../../../src/test/test-model'
const suiteWithChildren = (children: Array>) => {
const suite = new Suite({ id: '1', title: '', hooks: [] }, 0)
- suite.children = children as Array
+ suite.children = children.map((child) => ({ type: 'test', ...child })) as Array
return suite
}
@@ -44,19 +44,19 @@ describe('Suite model', () => {
it('is processing when all children are active', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'active' }])
- expect(suite.state).to.equal('processing')
+ expect(suite.state).to.equal('active')
})
it('is processing when there are active tests with passing tests', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'passed' }])
- expect(suite.state).to.equal('processing')
+ expect(suite.state).to.equal('active')
})
it('is processing when there are active tests with pending tests', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'pending' }])
- expect(suite.state).to.equal('processing')
+ expect(suite.state).to.equal('active')
})
it('is processing when all children are processing', () => {
From e7a4556eb7c84bbdcf898182e501ae0c88bc08cb Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 20 Jun 2025 15:05:17 -0400
Subject: [PATCH 47/48] add more tests for suite-model
---
.../cypress/e2e/unit/suite_model.cy.ts | 59 +++++++++++++++++--
1 file changed, 53 insertions(+), 6 deletions(-)
diff --git a/packages/reporter/cypress/e2e/unit/suite_model.cy.ts b/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
index 1c645a5227a2..7bdcb0411e2a 100644
--- a/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
+++ b/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
@@ -1,10 +1,10 @@
import Suite from '../../../src/runnables/suite-model'
import TestModel from '../../../src/test/test-model'
-const suiteWithChildren = (children: Array>) => {
- const suite = new Suite({ id: '1', title: '', hooks: [] }, 0)
+const suiteWithChildren = (children: Array>) => {
+ const suite = new Suite({ id: '1', title: '', hooks: [], suites: [], tests: [] }, 0)
- suite.children = children.map((child) => ({ type: 'test', ...child })) as Array
+ suite.children = children.map((child) => ({ type: 'test', ...child })) as Array
return suite
}
@@ -41,19 +41,19 @@ describe('Suite model', () => {
expect(suite.state).to.equal('passed')
})
- it('is processing when all children are active', () => {
+ it('is active when all children are active', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'active' }])
expect(suite.state).to.equal('active')
})
- it('is processing when there are active tests with passing tests', () => {
+ it('is active when there are active tests with passing tests', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'passed' }])
expect(suite.state).to.equal('active')
})
- it('is processing when there are active tests with pending tests', () => {
+ it('is active when there are active tests with pending tests', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'pending' }])
expect(suite.state).to.equal('active')
@@ -77,4 +77,51 @@ describe('Suite model', () => {
expect(suite.state).to.equal('processing')
})
})
+
+ describe('nested suites', () => {
+ it('is passed even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'passed', type: 'test' }, { state: 'active', type: 'suite' }, { state: 'failed', type: 'suite' }])
+
+ expect(suite.state).to.equal('passed')
+ expect(suite.children[0].state).to.equal('passed')
+ expect(suite.children[1].state).to.equal('active')
+ expect(suite.children[2].state).to.equal('failed')
+ })
+
+ it('is failed even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'failed' }, { state: 'passed', type: 'suite' }, { state: 'passed', type: 'suite' }])
+
+ expect(suite.state).to.equal('failed')
+ expect(suite.children[0].state).to.equal('failed')
+ expect(suite.children[1].state).to.equal('passed')
+ expect(suite.children[2].state).to.equal('passed')
+ })
+
+ it('is active even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'active' }, { state: 'processing', type: 'suite' }, { state: 'passed', type: 'suite' }])
+
+ expect(suite.state).to.equal('active')
+ expect(suite.children[0].state).to.equal('active')
+ expect(suite.children[1].state).to.equal('processing')
+ expect(suite.children[2].state).to.equal('passed')
+ })
+
+ it('is processing even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'processing' }, { state: 'passed', type: 'suite' }, { state: 'pending', type: 'suite' }])
+
+ expect(suite.state).to.equal('processing')
+ expect(suite.children[0].state).to.equal('processing')
+ expect(suite.children[1].state).to.equal('passed')
+ expect(suite.children[2].state).to.equal('pending')
+ })
+
+ it('is pending even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'pending' }, { state: 'passed', type: 'suite' }, { state: 'failed', type: 'suite' }])
+
+ expect(suite.state).to.equal('pending')
+ expect(suite.children[0].state).to.equal('pending')
+ expect(suite.children[1].state).to.equal('passed')
+ expect(suite.children[2].state).to.equal('failed')
+ })
+ })
})
From 9b83ab1eccfe27f559f2f2afd366f55ff3ef7dd4 Mon Sep 17 00:00:00 2001
From: Mabel Amaya
Date: Fri, 20 Jun 2025 17:56:27 -0400
Subject: [PATCH 48/48] fix more tests
---
.../cypress/e2e/cypress-in-cypress-e2e.cy.ts | 1 -
.../app/cypress/e2e/cypress-in-cypress.cy.ts | 3 +--
.../cypress/e2e/runner/reporter.hooks.cy.ts | 18 ++++++++++++++----
.../app/cypress/e2e/runner/runner.ui.cy.ts | 5 +++--
packages/app/cypress/e2e/specs_list_e2e.cy.ts | 5 +----
5 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts b/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts
index 14e709847ca9..1396fd34eaac 100644
--- a/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts
+++ b/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts
@@ -213,7 +213,6 @@ describe('Cypress In Cypress E2E', { viewportWidth: 1500, defaultCommandTimeout:
cy.visitApp()
cy.specsPageIsVisible()
cy.contains('withFailure.spec').click()
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.get('[data-cy="runnable-header"]').should('be.visible')
cy.get('body').type('f')
diff --git a/packages/app/cypress/e2e/cypress-in-cypress.cy.ts b/packages/app/cypress/e2e/cypress-in-cypress.cy.ts
index ea471e346152..a8399597cec7 100644
--- a/packages/app/cypress/e2e/cypress-in-cypress.cy.ts
+++ b/packages/app/cypress/e2e/cypress-in-cypress.cy.ts
@@ -131,8 +131,7 @@ describe('Cypress in Cypress', { viewportWidth: 1500, defaultCommandTimeout: 100
// validate that the width we set in `withCtx` above is the starting point
cy.get(`[data-cy="reporter-panel"]`).invoke('outerWidth').should('eq', 800)
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
- .click({ force: true })
+ cy.findByTestId('toggle-specs-button').click({ force: true })
// this tooltip text confirms specs list is open
cy.contains('Collapse Specs List')
diff --git a/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts b/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts
index 8b15e7d3f49c..82d764653e4d 100644
--- a/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts
+++ b/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts
@@ -53,11 +53,11 @@ describe('hooks', {
o.sinon.stub(ctx.actions.file, 'openFile')
})
- cy.contains('Open in IDE').invoke('show').click({ force: true })
+ cy.get('.open-in-ide-button').invoke('show').click()
cy.withCtx((ctx, o) => {
- expect(ctx.actions.file.openFile).to.have.been.calledWith(o.sinon.match(new RegExp(`hooks/basic\.cy\.js$`)), o.ideLine, o.ideColumn)
- }, { ideLine: 2, ideColumn: Cypress.browser.family === 'firefox' ? 5 : 2 })
+ expect(ctx.actions.file.openFile).to.have.been.calledWith(o.sinon.match(new RegExp(`hooks/basic\.cy\.js$`)), 1, 1)
+ })
})
it('does not display commands from skipped tests', () => {
@@ -84,12 +84,22 @@ describe('hooks', {
passCount: 1,
})
- cy.contains('test wrapper').parents('.collapsible').first().should(($suite) => {
+ cy.contains('test wrapper > nested suite 1').parents('.collapsible').first().should(($suite) => {
expect($suite).not.to.contain('test 1')
expect($suite).to.contain('nested suite 1')
expect($suite).to.contain('test 2')
expect($suite).not.to.contain('nested suite 2')
expect($suite).not.to.contain('test 3')
+ expect($suite).not.to.contain('nested suite 3')
+ expect($suite).not.to.contain('test 4')
+ })
+
+ cy.contains('test wrapper > nested suite 3').parents('.collapsible').first().should(($suite) => {
+ expect($suite).not.to.contain('test 1')
+ expect($suite).not.to.contain('nested suite 1')
+ expect($suite).not.to.contain('test 2')
+ expect($suite).not.to.contain('nested suite 2')
+ expect($suite).not.to.contain('test 3')
expect($suite).to.contain('nested suite 3')
expect($suite).to.contain('test 4')
})
diff --git a/packages/app/cypress/e2e/runner/runner.ui.cy.ts b/packages/app/cypress/e2e/runner/runner.ui.cy.ts
index be616e889512..5d574b6e50d6 100644
--- a/packages/app/cypress/e2e/runner/runner.ui.cy.ts
+++ b/packages/app/cypress/e2e/runner/runner.ui.cy.ts
@@ -171,8 +171,9 @@ describe('src/cypress/runner', () => {
o.sinon.stub(ctx.actions.file, 'openFile')
})
- cy.contains('a', 'simple-cy-assert.runner')
- .click()
+ cy.get('.open-in-ide-button').should('not.be.visible')
+ cy.get('.runnable-header-file-name').realHover()
+ cy.get('.open-in-ide-button').should('be.visible').click()
cy.withCtx((ctx, o) => {
expect(ctx.actions.file.openFile).to.have.been.calledWith(o.sinon.match(new RegExp(`simple-cy-assert\.runner\.cy\.js$`)), 1, 1)
diff --git a/packages/app/cypress/e2e/specs_list_e2e.cy.ts b/packages/app/cypress/e2e/specs_list_e2e.cy.ts
index 58818aed91b7..1dcb1fc42120 100644
--- a/packages/app/cypress/e2e/specs_list_e2e.cy.ts
+++ b/packages/app/cypress/e2e/specs_list_e2e.cy.ts
@@ -119,7 +119,6 @@ describe('App: Spec List (E2E)', () => {
cy.findAllByTestId('spec-item-link').should('have.attr', 'href')
cy.findAllByTestId('spec-item-link').contains('dom-content.spec.js').click()
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.findByText('Your tests are loading...').should('not.be.visible')
cy.get('[data-cy="runnable-header"]').should('be.visible')
cy.get('body').type('f')
@@ -133,10 +132,8 @@ describe('App: Spec List (E2E)', () => {
cy.findAllByTestId('spec-item-link').contains('accounts_list.spec.js').click()
// ensure the tests are loaded
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.findByText('Your tests are loading...').should('not.be.visible')
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.get('[data-cy="runnable-header"]').should('be.visible')
// open the inline spec list
cy.get('body').type('f')
@@ -369,7 +366,7 @@ describe('App: Spec List (E2E)', () => {
// A bit of a hack, but our cy-in-cy test needs to wait for the reporter to fully render before expanding the "Search specs" menu.
// Otherwise, the click happens before the event is registered, which causes the "Search Specs" menu to not expand.
cy.get('[data-cy="runnable-header"]').should('be.visible')
- cy.contains('button', 'Specs').click({ force: true })
+ cy.findByTestId('toggle-specs-button').click({ force: true })
// wait until specs list is visible
cy.findByTestId('specs-list-container').should('be.visible')