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'> - -
-
- {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'> +
+ +
+
+ {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) && ( - - - + )}
) 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)) && ( )} -
+ ) } 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)) && ( - 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)) && ( - 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'>
+ } + 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'>
- {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'> - -
- ))} - {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'> + +
+ ))} + {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) && ( -