diff --git a/.circleci/cache-version.txt b/.circleci/cache-version.txt
index 948de64c5a39..4ee70cb0d70c 100644
--- a/.circleci/cache-version.txt
+++ b/.circleci/cache-version.txt
@@ -1,3 +1,3 @@
# Bump this version to force CI to re-create the cache from scratch.
-6-9-2025
+6-30-2025
diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml
index b1b5da917fdb..e80dc0f07d16 100644
--- a/.circleci/workflows.yml
+++ b/.circleci/workflows.yml
@@ -38,7 +38,7 @@ mainBuildFilters: &mainBuildFilters
- /^release\/\d+\.\d+\.\d+$/
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- 'update-v8-snapshot-cache-on-develop'
- - 'chore/test_cypress_recipes_15'
+ - 'mabel/issue-31677-reporter-redesign'
# usually we don't build Mac app - it takes a long time
# but sometimes we want to really confirm we are doing the right thing
@@ -49,7 +49,7 @@ macWorkflowFilters: &darwin-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- - equal: [ 'chore/test_cypress_recipes_15', << pipeline.git.branch >> ]
+ - equal: [ 'mabel/issue-31677-reporter-redesign', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -60,7 +60,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- - equal: [ 'chore/test_cypress_recipes_15', << pipeline.git.branch >> ]
+ - equal: [ 'mabel/issue-31677-reporter-redesign', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -83,7 +83,7 @@ windowsWorkflowFilters: &windows-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- - equal: [ 'chore/test_cypress_recipes_15', << pipeline.git.branch >> ]
+ - equal: [ 'mabel/issue-31677-reporter-redesign', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -157,7 +157,7 @@ commands:
name: Set environment variable to determine whether or not to persist artifacts
command: |
echo "Setting SHOULD_PERSIST_ARTIFACTS variable"
- echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "chore/test_cypress_recipes_15" ]]; then
+ echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "mabel/issue-31677-reporter-redesign" ]]; then
export SHOULD_PERSIST_ARTIFACTS=true
fi' >> "$BASH_ENV"
# You must run `setup_should_persist_artifacts` command and be using bash before running this command
diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md
index 503c9e3eed4c..644503814d40 100644
--- a/cli/CHANGELOG.md
+++ b/cli/CHANGELOG.md
@@ -26,6 +26,7 @@ _Released 07/15/2025 (PENDING)_
**Misc:**
+- The Cypress Command log has a new design when viewing a list of tests. Addresses [#31677](https://github.com/cypress-io/cypress/issues/31677). Addressed in [#31914](https://github.com/cypress-io/cypress/pull/31914).
- Migration helpers and related errors are no longer shown when upgrading from Cypress versions earlier than 10.0.0. To migrate from a pre-10.0.0 version, upgrade one major version at a time to receive the appropriate guidance. Addresses [#31345](https://github.com/cypress-io/cypress/issues/31345). Addressed in [https://github.com/cypress-io/cypress/pull/31629/](https://github.com/cypress-io/cypress/pull/31629/).
## 14.5.1
diff --git a/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts b/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts
index 14e709847ca9..1396fd34eaac 100644
--- a/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts
+++ b/packages/app/cypress/e2e/cypress-in-cypress-e2e.cy.ts
@@ -213,7 +213,6 @@ describe('Cypress In Cypress E2E', { viewportWidth: 1500, defaultCommandTimeout:
cy.visitApp()
cy.specsPageIsVisible()
cy.contains('withFailure.spec').click()
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.get('[data-cy="runnable-header"]').should('be.visible')
cy.get('body').type('f')
diff --git a/packages/app/cypress/e2e/cypress-in-cypress.cy.ts b/packages/app/cypress/e2e/cypress-in-cypress.cy.ts
index ea471e346152..a8399597cec7 100644
--- a/packages/app/cypress/e2e/cypress-in-cypress.cy.ts
+++ b/packages/app/cypress/e2e/cypress-in-cypress.cy.ts
@@ -131,8 +131,7 @@ describe('Cypress in Cypress', { viewportWidth: 1500, defaultCommandTimeout: 100
// validate that the width we set in `withCtx` above is the starting point
cy.get(`[data-cy="reporter-panel"]`).invoke('outerWidth').should('eq', 800)
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
- .click({ force: true })
+ cy.findByTestId('toggle-specs-button').click({ force: true })
// this tooltip text confirms specs list is open
cy.contains('Collapse Specs List')
diff --git a/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts b/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts
index 8b15e7d3f49c..328dc0934813 100644
--- a/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts
+++ b/packages/app/cypress/e2e/runner/reporter.hooks.cy.ts
@@ -53,11 +53,11 @@ describe('hooks', {
o.sinon.stub(ctx.actions.file, 'openFile')
})
- cy.contains('Open in IDE').invoke('show').click({ force: true })
+ cy.get('.hook-open-in-ide').first().invoke('show').click()
cy.withCtx((ctx, o) => {
- expect(ctx.actions.file.openFile).to.have.been.calledWith(o.sinon.match(new RegExp(`hooks/basic\.cy\.js$`)), o.ideLine, o.ideColumn)
- }, { ideLine: 2, ideColumn: Cypress.browser.family === 'firefox' ? 5 : 2 })
+ expect(ctx.actions.file.openFile).to.have.been.calledWith(o.sinon.match(new RegExp(`hooks/basic\.cy\.js$`)), 2, 2)
+ })
})
it('does not display commands from skipped tests', () => {
@@ -67,9 +67,7 @@ describe('hooks', {
})
// does not display commands from skipped tests
- cy.contains('test 1').click()
- cy.contains('test 1').parents('.collapsible').first().should('not.contain', 'testBody 1')
- cy.contains('test 1').click()
+ cy.contains('test 1').should('have.css', 'pointer-events', 'none')
// displays before hook when following it.skip
// https://github.com/cypress-io/cypress/issues/8086
@@ -84,12 +82,22 @@ describe('hooks', {
passCount: 1,
})
- cy.contains('test wrapper').parents('.collapsible').first().should(($suite) => {
+ cy.contains('test wrapper > nested suite 1').parents('.collapsible').first().should(($suite) => {
expect($suite).not.to.contain('test 1')
expect($suite).to.contain('nested suite 1')
expect($suite).to.contain('test 2')
expect($suite).not.to.contain('nested suite 2')
expect($suite).not.to.contain('test 3')
+ expect($suite).not.to.contain('nested suite 3')
+ expect($suite).not.to.contain('test 4')
+ })
+
+ cy.contains('test wrapper > nested suite 3').parents('.collapsible').first().should(($suite) => {
+ expect($suite).not.to.contain('test 1')
+ expect($suite).not.to.contain('nested suite 1')
+ expect($suite).not.to.contain('test 2')
+ expect($suite).not.to.contain('nested suite 2')
+ expect($suite).not.to.contain('test 3')
expect($suite).to.contain('nested suite 3')
expect($suite).to.contain('test 4')
})
diff --git a/packages/app/cypress/e2e/runner/runner.ui.cy.ts b/packages/app/cypress/e2e/runner/runner.ui.cy.ts
index be616e889512..b7aa08b9882f 100644
--- a/packages/app/cypress/e2e/runner/runner.ui.cy.ts
+++ b/packages/app/cypress/e2e/runner/runner.ui.cy.ts
@@ -171,8 +171,9 @@ describe('src/cypress/runner', () => {
o.sinon.stub(ctx.actions.file, 'openFile')
})
- cy.contains('a', 'simple-cy-assert.runner')
- .click()
+ cy.get('.open-in-ide-button').should('have.css', 'opacity', '0')
+ cy.get('.runnable-header-file-name').realHover()
+ cy.get('.open-in-ide-button').first().should('have.css', 'opacity', '1').click()
cy.withCtx((ctx, o) => {
expect(ctx.actions.file.openFile).to.have.been.calledWith(o.sinon.match(new RegExp(`simple-cy-assert\.runner\.cy\.js$`)), 1, 1)
diff --git a/packages/app/cypress/e2e/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/spec-loader.ts b/packages/app/cypress/e2e/runner/support/spec-loader.ts
index 651a6a611153..94182aff830e 100644
--- a/packages/app/cypress/e2e/runner/support/spec-loader.ts
+++ b/packages/app/cypress/e2e/runner/support/spec-loader.ts
@@ -5,9 +5,10 @@ export const shouldHaveTestResults = ({ passCount, failCount, pendingCount }) =>
failCount = failCount || '--'
cy.get('button.restart', { timeout: 30000 }).should('be.visible') // ensure tests are finished running
- cy.findByLabelText('Stats', { timeout: 10000 }).within(() => {
- cy.get('.passed .num', { timeout: 30000 }).should('have.text', `${passCount}`)
- cy.get('.failed .num', { timeout: 30000 }).should('have.text', `${failCount}`)
+
+ cy.get('.stats', { timeout: 10000 }).within(() => {
+ cy.get('.passed .num', { timeout: 40000 }).should('have.text', `${passCount}`)
+ cy.get('.failed .num', { timeout: 40000 }).should('have.text', `${failCount}`)
if (pendingCount) {
cy.get('.pending .num', { timeout: 20000 }).should('have.text', `${pendingCount}`)
diff --git a/packages/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/app/cypress/e2e/specs_list_component.cy.ts b/packages/app/cypress/e2e/specs_list_component.cy.ts
index 6dffbbc57eb3..3ee75ebfb107 100644
--- a/packages/app/cypress/e2e/specs_list_component.cy.ts
+++ b/packages/app/cypress/e2e/specs_list_component.cy.ts
@@ -26,7 +26,7 @@ describe('App: Spec List (Component)', () => {
it('highlights the currently running spec', () => {
cy.contains('fails').click()
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
+
cy.get('[data-cy="runnable-header"]').should('be.visible')
cy.get('body').type('f')
cy.get('[data-selected-spec="true"]').should('contain', 'fails')
diff --git a/packages/app/cypress/e2e/specs_list_e2e.cy.ts b/packages/app/cypress/e2e/specs_list_e2e.cy.ts
index 58818aed91b7..1dcb1fc42120 100644
--- a/packages/app/cypress/e2e/specs_list_e2e.cy.ts
+++ b/packages/app/cypress/e2e/specs_list_e2e.cy.ts
@@ -119,7 +119,6 @@ describe('App: Spec List (E2E)', () => {
cy.findAllByTestId('spec-item-link').should('have.attr', 'href')
cy.findAllByTestId('spec-item-link').contains('dom-content.spec.js').click()
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.findByText('Your tests are loading...').should('not.be.visible')
cy.get('[data-cy="runnable-header"]').should('be.visible')
cy.get('body').type('f')
@@ -133,10 +132,8 @@ describe('App: Spec List (E2E)', () => {
cy.findAllByTestId('spec-item-link').contains('accounts_list.spec.js').click()
// ensure the tests are loaded
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.findByText('Your tests are loading...').should('not.be.visible')
- cy.contains('[aria-controls=reporter-inline-specs-list]', 'Specs')
cy.get('[data-cy="runnable-header"]').should('be.visible')
// open the inline spec list
cy.get('body').type('f')
@@ -369,7 +366,7 @@ describe('App: Spec List (E2E)', () => {
// A bit of a hack, but our cy-in-cy test needs to wait for the reporter to fully render before expanding the "Search specs" menu.
// Otherwise, the click happens before the event is registered, which causes the "Search Specs" menu to not expand.
cy.get('[data-cy="runnable-header"]').should('be.visible')
- cy.contains('button', 'Specs').click({ force: true })
+ cy.findByTestId('toggle-specs-button').click({ force: true })
// wait until specs list is visible
cy.findByTestId('specs-list-container').should('be.visible')
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/driver/cypress/support/utils.ts b/packages/driver/cypress/support/utils.ts
index 486f2dd40e4e..08ef205d357b 100644
--- a/packages/driver/cypress/support/utils.ts
+++ b/packages/driver/cypress/support/utils.ts
@@ -9,7 +9,7 @@ export const getCommandLogWithText = (command, type?) => {
cy.$$('.runnable-active .collapsible:not(.is-open) .collapsible-header', top?.document).click()
return cy
- .$$(`.runnable-active .command-${type}:contains(${command})`, top?.document)
+ .$$(`.test.runnable-active .command-${type}:contains(${command})`, top?.document)
.closest('.command')
}
diff --git a/packages/frontend-shared/package.json b/packages/frontend-shared/package.json
index a432ec5ae80f..75fba94bc8c8 100644
--- a/packages/frontend-shared/package.json
+++ b/packages/frontend-shared/package.json
@@ -88,7 +88,6 @@
"just-my-luck": "3.0.0",
"lodash": "4.17.21",
"markdown-it": "13.0.1",
- "modern-normalize": "1.1.0",
"nock": "13.2.9",
"p-defer": "^3.0.0",
"patch-package": "8.0.0",
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/frontend-shared/src/styles/normalize.scss b/packages/frontend-shared/src/styles/normalize.scss
deleted file mode 100644
index 16ca33e1e3e3..000000000000
--- a/packages/frontend-shared/src/styles/normalize.scss
+++ /dev/null
@@ -1,825 +0,0 @@
-/**
- * Tailwind's Preflight Style Reset
- * https://tailwindcss.com/docs/preflight
- *
- * Why is this here?
- * 1. Tailwind doesn't publish their style reset (which is
- * derived from modern-normalize).
- * 2. TailwindCSS's version of this doesn't work with third-party
- * DOM elements that it can't extract.
- */
-
- /*! tailwindcss v2.2.16 | MIT License | https://tailwindcss.com */
-/*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
-@use 'modern-normalize/modern-normalize.css';
-
-/*
-Document
-========
-*/
-
-/**
-Use a better box model (opinionated).
-*/
-
-*,
-::before,
-::after {
- box-sizing: border-box;
-}
-
-/**
-Use a more readable tab size (opinionated).
-*/
-
-html {
- -moz-tab-size: 4;
- tab-size: 4;
-}
-
-/**
-1. Correct the line height in all browsers.
-2. Prevent adjustments of font size after orientation changes in iOS.
-*/
-
-html {
- line-height: 1.15; /* 1 */
- -webkit-text-size-adjust: 100%; /* 2 */
-}
-
-/*
-Sections
-========
-*/
-
-/**
-Remove the margin in all browsers.
-*/
-
-body {
- margin: 0;
-}
-
-/**
-Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
-*/
-
-body {
- font-family:
- system-ui,
- -apple-system, /* Firefox supports this but not yet `system-ui` */
- 'Segoe UI',
- Roboto,
- Helvetica,
- Arial,
- sans-serif,
- 'Apple Color Emoji',
- 'Segoe UI Emoji';
-}
-
-/*
-Grouping content
-================
-*/
-
-/**
-1. Add the correct height in Firefox.
-2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
-*/
-
-hr {
- height: 0; /* 1 */
- color: inherit; /* 2 */
-}
-
-/*
-Text-level semantics
-====================
-*/
-
-/**
-Add the correct text decoration in Chrome, Edge, and Safari.
-*/
-
-abbr[title] {
- -webkit-text-decoration: underline dotted;
- text-decoration: underline dotted;
-}
-
-/**
-Add the correct font weight in Edge and Safari.
-*/
-
-b,
-strong {
- font-weight: bolder;
-}
-
-/**
-1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
-2. Correct the odd 'em' font sizing in all browsers.
-*/
-
-code,
-kbd,
-samp,
-pre {
- font-family:
- ui-monospace,
- SFMono-Regular,
- Consolas,
- 'Liberation Mono',
- Menlo,
- monospace; /* 1 */
- font-size: 1em; /* 2 */
-}
-
-/**
-Add the correct font size in all browsers.
-*/
-
-small {
- font-size: 80%;
-}
-
-/**
-Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
-*/
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-sup {
- top: -0.5em;
-}
-
-/*
-Tabular data
-============
-*/
-
-/**
-1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
-2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
-*/
-
-table {
- text-indent: 0; /* 1 */
- border-color: inherit; /* 2 */
-}
-
-/*
-Forms
-=====
-*/
-
-/**
-1. Change the font styles in all browsers.
-2. Remove the margin in Firefox and Safari.
-*/
-
-button,
-input,
-optgroup,
-select,
-textarea {
- font-family: inherit; /* 1 */
- font-size: 100%; /* 1 */
- line-height: 1.15; /* 1 */
- margin: 0; /* 2 */
-}
-
-/**
-Remove the inheritance of text transform in Edge and Firefox.
-1. Remove the inheritance of text transform in Firefox.
-*/
-
-button,
-select { /* 1 */
- text-transform: none;
-}
-
-/**
-Correct the inability to style clickable types in iOS and Safari.
-*/
-
-button,
-[type='button'],
-[type='reset'],
-[type='submit'] {
- -webkit-appearance: button;
-}
-
-/**
-Remove the inner border and padding in Firefox.
-*/
-
-::-moz-focus-inner {
- border-style: none;
- padding: 0;
-}
-
-/**
-Restore the focus styles unset by the previous rule.
-*/
-
-:-moz-focusring {
- outline: 1px dotted ButtonText;
-}
-
-/**
-Remove the additional ':invalid' styles in Firefox.
-See: https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737
-*/
-
-:-moz-ui-invalid {
- box-shadow: none;
-}
-
-/**
-Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.
-*/
-
-legend {
- padding: 0;
-}
-
-/**
-Add the correct vertical alignment in Chrome and Firefox.
-*/
-
-progress {
- vertical-align: baseline;
-}
-
-/**
-Correct the cursor style of increment and decrement buttons in Safari.
-*/
-
-::-webkit-inner-spin-button,
-::-webkit-outer-spin-button {
- height: auto;
-}
-
-/**
-1. Correct the odd appearance in Chrome and Safari.
-2. Correct the outline style in Safari.
-*/
-
-[type='search'] {
- -webkit-appearance: textfield; /* 1 */
- outline-offset: -2px; /* 2 */
-}
-
-/**
-Remove the inner padding in Chrome and Safari on macOS.
-*/
-
-::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-/**
-1. Correct the inability to style clickable types in iOS and Safari.
-2. Change font properties to 'inherit' in Safari.
-*/
-
-::-webkit-file-upload-button {
- -webkit-appearance: button; /* 1 */
- font: inherit; /* 2 */
-}
-
-/*
-Interactive
-===========
-*/
-
-/*
-Add the correct display in Chrome and Safari.
-*/
-
-summary {
- display: list-item;
-}
-
-/**
- * Manually forked from SUIT CSS Base: https://github.com/suitcss/base
- * A thin layer on top of normalize.css that provides a starting point more
- * suitable for web applications.
- */
-
-/**
- * Removes the default spacing and border for appropriate elements.
- */
-
-blockquote,
-dl,
-dd,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-hr,
-figure,
-p,
-pre {
- margin: 0;
-}
-
-button {
- background-color: transparent;
- background-image: none;
-}
-
-fieldset {
- margin: 0;
- padding: 0;
-}
-
-ol,
-ul {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-/**
- * Tailwind custom reset styles
- */
-
-/**
- * 1. Use the user's configured `sans` font-family (with Tailwind's default
- * sans-serif font stack as a fallback) as a sane default.
- * 2. Use Tailwind's default "normal" line-height so the user isn't forced
- * to override it to ensure consistency even when using the default theme.
- */
-
-html {
- font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 1 */
- line-height: 1.5; /* 2 */
-}
-
-/**
- * Inherit font-family and line-height from `html` so users can set them as
- * a class directly on the `html` element.
- */
-
-body {
- font-family: inherit;
- line-height: inherit;
-}
-
-/**
- * 1. Prevent padding and border from affecting element width.
- *
- * We used to set this in the html element and inherit from
- * the parent element for everything else. This caused issues
- * in shadow-dom-enhanced elements like where the content
- * is wrapped by a div with box-sizing set to `content-box`.
- *
- * https://github.com/mozdevs/cssremedy/issues/4
- *
- *
- * 2. Allow adding a border to an element by just adding a border-width.
- *
- * By default, the way the browser specifies that an element should have no
- * border is by setting it's border-style to `none` in the user-agent
- * stylesheet.
- *
- * In order to easily add borders to elements by just setting the `border-width`
- * property, we change the default border-style for all elements to `solid`, and
- * use border-width to hide them instead. This way our `border` utilities only
- * need to set the `border-width` property instead of the entire `border`
- * shorthand, making our border utilities much more straightforward to compose.
- *
- * https://github.com/tailwindcss/tailwindcss/pull/116
- */
-
-*,
-::before,
-::after {
- box-sizing: border-box; /* 1 */
- border-width: 0; /* 2 */
- border-style: solid; /* 2 */
- border-color: currentColor; /* 2 */
-}
-
-/*
- * Ensure horizontal rules are visible by default
- */
-
-hr {
- border-top-width: 1px;
-}
-
-/**
- * Undo the `border-style: none` reset that Normalize applies to images so that
- * our `border-{width}` utilities have the expected effect.
- *
- * The Normalize reset is unnecessary for us since we default the border-width
- * to 0 on all elements.
- *
- * https://github.com/tailwindcss/tailwindcss/issues/362
- */
-
-img {
- border-style: solid;
-}
-
-textarea {
- resize: vertical;
-}
-
-input::placeholder,
-textarea::placeholder {
- opacity: 1;
- color: #9ca3af;
-}
-
-button,
-[role="button"] {
- cursor: pointer;
-}
-
-/**
- * Override legacy focus reset from Normalize with modern Firefox focus styles.
- *
- * This is actually an improvement over the new defaults in Firefox in our testing,
- * as it triggers the better focus styles even for links, which still use a dotted
- * outline in Firefox by default.
- */
-
-:-moz-focusring {
- outline: auto;
-}
-
-table {
- border-collapse: collapse;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- font-size: inherit;
- font-weight: inherit;
-}
-
-/**
- * Reset links to optimize for opt-in styling instead of
- * opt-out.
- */
-
-a {
- color: inherit;
- text-decoration: inherit;
-}
-
-/**
- * Reset form element properties that are easy to forget to
- * style explicitly so you don't inadvertently introduce
- * styles that deviate from your design system. These styles
- * supplement a partial reset that is already applied by
- * normalize.css.
- */
-
-button,
-input,
-optgroup,
-select,
-textarea {
- padding: 0;
- line-height: inherit;
- color: inherit;
-}
-
-/**
- * Use the configured 'mono' font family for elements that
- * are expected to be rendered with a monospace font, falling
- * back to the system monospace stack if there is no configured
- * 'mono' font family.
- */
-
-pre,
-code,
-kbd,
-samp {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
-}
-
-/**
- * 1. Make replaced elements `display: block` by default as that's
- * the behavior you want almost all of the time. Inspired by
- * CSS Remedy, with `svg` added as well.
- *
- * https://github.com/mozdevs/cssremedy/issues/14
- *
- * 2. Add `vertical-align: middle` to align replaced elements more
- * sensibly by default when overriding `display` by adding a
- * utility like `inline`.
- *
- * This can trigger a poorly considered linting error in some
- * tools but is included by design.
- *
- * https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210
- */
-
-img,
-svg,
-video,
-canvas,
-audio,
-iframe,
-embed,
-object {
- display: block; /* 1 */
- vertical-align: middle; /* 2 */
-}
-
-/**
- * Constrain images and videos to the parent width and preserve
- * their intrinsic aspect ratio.
- *
- * https://github.com/mozdevs/cssremedy/issues/14
- */
-
-img,
-video {
- max-width: 100%;
- height: auto;
-}
-
-/**
- * Ensure the default browser behavior of the `hidden` attribute.
- */
-
-[hidden] {
- display: none;
-}
-
-*, ::before, ::after {
- --tw-border-opacity: 1;
- border-color: rgba(229, 231, 235, var(--tw-border-opacity));
-}
-
-
-/*
-* Global Resets
-* -------------------------
-*/
-
-// Input Resets
-// Taken from Tailwind CSS Forms -- a plugin for tailwind.
-// We could probably add these into TailwindCSS directly
-// https://github.com/tailwindlabs/tailwindcss-forms
-
-[multiple],
-[type=date],
-[type=datetime-local],
-[type=email],
-[type=month],
-[type=number],
-[type=password],
-[type=search],
-[type=tel],
-[type=text],
-[type=time],
-[type=url],
-[type=week],
-select,
-textarea {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-color: #fff;
- border-color: #6b7280;
- border-width: 1px;
- border-radius: 0;
- padding-top: 0.35rem;
- padding-bottom: 0.35rem;
- padding-left: 0.5rem;
- padding-right: 0.5rem;
- font-size: 1rem;
- line-height: 1.25rem;
-}
-
-[multiple]:focus,
-[type=date]:focus,
-[type=datetime-local]:focus,
-[type=email]:focus,
-[type=month]:focus,
-[type=number]:focus,
-[type=password]:focus,
-[type=search]:focus,
-[type=tel]:focus,
-[type=text]:focus,
-[type=time]:focus,
-[type=url]:focus,
-[type=week]:focus,
-select:focus,
-textarea:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
- --tw-ring-inset: var(--tw-empty, );
- /*!*/
- /*!*/
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: #2563eb;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- border-color: #2563eb;
-}
-
-input::-moz-placeholder,
-textarea::-moz-placeholder {
- color: #6b7280;
- opacity: 1;
-}
-
-input:-ms-input-placeholder,
-textarea:-ms-input-placeholder {
- color: #6b7280;
- opacity: 1;
-}
-
-input::placeholder,
-textarea::placeholder {
- color: #6b7280;
- opacity: 1;
-}
-
-::-webkit-datetime-edit-fields-wrapper {
- padding: 0;
-}
-
-::-webkit-date-and-time-value {
- min-height: 1.5em;
-}
-
-select {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
- background-position: right .5rem center;
- background-repeat: no-repeat;
- background-size: 1.5em 1.5em;
- padding-right: 2.5rem;
- -webkit-print-color-adjust: exact;
- print-color-adjust: exact;
-}
-
-[multiple] {
- background-image: initial;
- background-position: initial;
- background-repeat: unset;
- background-size: initial;
- padding-right: .75rem;
- -webkit-print-color-adjust: unset;
- print-color-adjust: unset;
-}
-
-[type=checkbox],
-[type=radio] {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- padding: 0;
- -webkit-print-color-adjust: exact;
- print-color-adjust: exact;
- display: inline-block;
- vertical-align: middle;
- background-origin: border-box;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- flex-shrink: 0;
- height: 1rem;
- width: 1rem;
- color: #2563eb;
- background-color: #fff;
- border-color: #6b7280;
- border-width: 1px;
-}
-
-[type=checkbox] {
- border-radius: 0;
-}
-
-[type=radio] {
- border-radius: 100%;
-}
-
-[type=checkbox]:focus,
-[type=radio]:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
- --tw-ring-inset: var(--tw-empty);
- --tw-ring-offset-width: 2px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: #2563eb;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
-}
-
-[type=checkbox]:checked,
-[type=radio]:checked {
- border-color: transparent;
- background-color: currentColor;
- background-size: 100% 100%;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-[type=checkbox]:checked {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
-}
-
-[type=radio]:checked {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
-}
-
-[type=checkbox]:checked:focus,
-[type=checkbox]:checked:hover,
-[type=radio]:checked:focus,
-[type=radio]:checked:hover {
- border-color: transparent;
- background-color: currentColor;
-}
-
-[type=checkbox]:indeterminate {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
- border-color: transparent;
- background-color: currentColor;
- background-size: 100% 100%;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-[type=checkbox]:indeterminate:focus,
-[type=checkbox]:indeterminate:hover {
- border-color: transparent;
- background-color: currentColor;
-}
-
-[type=file] {
- background: unset;
- border-color: inherit;
- border-width: 0;
- border-radius: 0;
- padding: 0;
- font-size: unset;
- line-height: inherit;
-}
-
-[type=file]:focus {
- outline: 1px auto -webkit-focus-ring-color;
-}
-
-
-input[type="search"].dark {
- background: #222;
- color: #fff;
-}
-
-input[type="search"].light {
- background: #fff;
- color: #222;
-}
-input[type="search"].suffix::-webkit-search-cancel-button {
- @apply pr-[3.25em];
-}
-
-input[type="search"]::-webkit-search-cancel-button {
- -webkit-appearance: none;
- margin: 1em;
- height: 1em;
- width: 1em;
- border-radius: 50em;
- background: url(https://pro.fontawesome.com/releases/v5.10.0/svgs/solid/times-circle.svg)
- no-repeat 50% 50%;
- background-size: contain;
- opacity: 0;
- pointer-events: none;
-}
-
-input[type="search"]:focus::-webkit-search-cancel-button {
- opacity: 0.3;
- pointer-events: all;
-}
-
-input[type="search"].dark::-webkit-search-cancel-button {
- filter: invert(1);
-}
diff --git a/packages/frontend-shared/src/styles/shared.scss b/packages/frontend-shared/src/styles/shared.scss
index 708128d3ad66..c60c88b0946b 100644
--- a/packages/frontend-shared/src/styles/shared.scss
+++ b/packages/frontend-shared/src/styles/shared.scss
@@ -1,4 +1,3 @@
-@use './normalize.scss';
/* Define the "system" font family */
@font-face {
@@ -61,257 +60,4 @@ body {
::selection {
@apply bg-gray-200 bg-opacity-30;
-}
-
-/**
- * Global Resets
- * -------------------------
- */
-
-// Input Resets
-// Taken from Tailwind CSS Forms -- a plugin for tailwind.
-// We could probably add these into TailwindCSS directly
-// https://github.com/tailwindlabs/tailwindcss-forms
-// [type="search"]::-webkit-search-cancel-button,
-// [type="search"]::-webkit-search-decoration {
-// -webkit-appearance: none !important;
-// appearance: none !important;
-// }
-
-[multiple],
-[type=date],
-[type=datetime-local],
-[type=email],
-[type=month],
-[type=number],
-[type=password],
-[type=search],
-[type=tel],
-[type=text],
-[type=time],
-[type=url],
-[type=week],
-select,
-textarea {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-color: #fff;
- border-color: #6b7280;
- border-width: 1px;
- border-radius: 0;
- padding-top: 0.35rem;
- padding-bottom: 0.35rem;
- padding-left: 0.5rem;
- padding-right: 0.5rem;
- font-size: 1rem;
- line-height: 1.25rem;
-}
-
-[multiple]:focus,
-[type=date]:focus,
-[type=datetime-local]:focus,
-[type=email]:focus,
-[type=month]:focus,
-[type=number]:focus,
-[type=password]:focus,
-[type=search]:focus,
-[type=tel]:focus,
-[type=text]:focus,
-[type=time]:focus,
-[type=url]:focus,
-[type=week]:focus,
-select:focus,
-textarea:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
- --tw-ring-inset: var(--tw-empty, );
- /*!*/
- /*!*/
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: #2563eb;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- border-color: #2563eb;
-}
-
-input::-moz-placeholder,
-textarea::-moz-placeholder {
- color: #6b7280;
- opacity: 1;
-}
-
-input:-ms-input-placeholder,
-textarea:-ms-input-placeholder {
- color: #6b7280;
- opacity: 1;
-}
-
-input::placeholder,
-textarea::placeholder {
- color: #6b7280;
- opacity: 1;
-}
-
-::-webkit-datetime-edit-fields-wrapper {
- padding: 0;
-}
-
-::-webkit-date-and-time-value {
- min-height: 1.5em;
-}
-
-select {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
- background-position: right .5rem center;
- background-repeat: no-repeat;
- background-size: 1.5em 1.5em;
- padding-right: 2.5rem;
- -webkit-print-color-adjust: exact;
- print-color-adjust: exact;
-}
-
-[multiple] {
- background-image: initial;
- background-position: initial;
- background-repeat: unset;
- background-size: initial;
- padding-right: .75rem;
- -webkit-print-color-adjust: unset;
- print-color-adjust: unset;
-}
-
-[type=checkbox],
-[type=radio] {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- padding: 0;
- -webkit-print-color-adjust: exact;
- print-color-adjust: exact;
- display: inline-block;
- vertical-align: middle;
- background-origin: border-box;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- flex-shrink: 0;
- height: 1rem;
- width: 1rem;
- color: #2563eb;
- background-color: #fff;
- border-color: #6b7280;
- border-width: 1px;
-}
-
-[type=checkbox] {
- border-radius: 0;
-}
-
-[type=radio] {
- border-radius: 100%;
-}
-
-[type=checkbox]:focus,
-[type=radio]:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
- --tw-ring-inset: var(--tw-empty);
- --tw-ring-offset-width: 2px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: #2563eb;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
-}
-
-[type=checkbox]:checked,
-[type=radio]:checked {
- border-color: transparent;
- background-color: currentColor;
- background-size: 100% 100%;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-[type=checkbox]:checked {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
-}
-
-[type=radio]:checked {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
-}
-
-[type=checkbox]:checked:focus,
-[type=checkbox]:checked:hover,
-[type=radio]:checked:focus,
-[type=radio]:checked:hover {
- border-color: transparent;
- background-color: currentColor;
-}
-
-[type=checkbox]:indeterminate {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
- border-color: transparent;
- background-color: currentColor;
- background-size: 100% 100%;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-[type=checkbox]:indeterminate:focus,
-[type=checkbox]:indeterminate:hover {
- border-color: transparent;
- background-color: currentColor;
-}
-
-[type=file] {
- background: unset;
- border-color: inherit;
- border-width: 0;
- border-radius: 0;
- padding: 0;
- font-size: unset;
- line-height: inherit;
-}
-
-[type=file]:focus {
- outline: 1px auto -webkit-focus-ring-color;
-}
-
-
-input[type="search"].dark {
- background: #222;
- color: #fff;
-}
-
-input[type="search"].light {
- background: #fff;
- color: #222;
-}
-input[type="search"].suffix::-webkit-search-cancel-button {
- @apply pr-[3.25em];
-}
-
-input[type="search"]::-webkit-search-cancel-button {
- -webkit-appearance: none;
- margin: 1em;
- height: 1em;
- width: 1em;
- border-radius: 50em;
- background: url(https://pro.fontawesome.com/releases/v5.10.0/svgs/solid/times-circle.svg)
- no-repeat 50% 50%;
- background-size: contain;
- opacity: 0;
- pointer-events: none;
-}
-
-input[type="search"]:focus::-webkit-search-cancel-button {
- opacity: 0.3;
- pointer-events: all;
-}
-
-input[type="search"].dark::-webkit-search-cancel-button {
- filter: invert(1);
-}
+}
\ No newline at end of file
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/cypress/e2e/commands.cy.ts b/packages/reporter/cypress/e2e/commands.cy.ts
index ce0267afb0ad..86f5ef0544d0 100644
--- a/packages/reporter/cypress/e2e/commands.cy.ts
+++ b/packages/reporter/cypress/e2e/commands.cy.ts
@@ -898,7 +898,10 @@ describe('commands', { viewportHeight: 1000 }, () => {
})
it('shows a tooltip', () => {
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
cy.get('.cy-tooltip').should('have.text', 'Printed output to your console')
})
@@ -911,21 +914,32 @@ describe('commands', { viewportHeight: 1000 }, () => {
it('prints to console', () => {
cy.spy(runner, 'emit')
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
cy.wrap(runner.emit).should('be.calledWith', 'runner:console:log', 'r3', fakeIdForTest)
})
it('shows the snapshot', () => {
cy.spy(runner, 'emit')
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
cy.wrap(runner.emit).should('be.calledWith', 'runner:show:snapshot', 'r3', fakeIdForTest)
})
it('unpins after clicking again, does not re-print to the console', () => {
cy.spy(runner, 'emit')
- cy.get('.command-name-within').click('top')
- cy.get('.command-name-within').click('top')
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
+ cy.get('.command-name-within').within(() => {
+ cy.contains('within').click()
+ })
+
// @ts-ignore
cy.wrap(runner.emit.withArgs('runner:console:log')).should('be.calledOnce')
})
diff --git a/packages/reporter/cypress/e2e/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/cypress/e2e/meta_&%.cy.ts b/packages/reporter/cypress/e2e/meta_&%.cy.ts
index 9afdea03c851..0f424b0cbc2c 100644
--- a/packages/reporter/cypress/e2e/meta_&%.cy.ts
+++ b/packages/reporter/cypress/e2e/meta_&%.cy.ts
@@ -3,7 +3,7 @@
describe('special characters', () => {
it('displays file name with decoded special characters', () => {
cy.wrap(Cypress.$(window.top.document.body))
- .find('.reporter .runnable-header a')
- .should('have.text', 'meta_&%.cy.ts')
+ .find('.reporter .runnable-header')
+ .contains('meta_&%.cy.ts')
})
})
diff --git a/packages/reporter/cypress/e2e/runnables.cy.ts b/packages/reporter/cypress/e2e/runnables.cy.ts
index eb108faa239d..966b8cd653d1 100644
--- a/packages/reporter/cypress/e2e/runnables.cy.ts
+++ b/packages/reporter/cypress/e2e/runnables.cy.ts
@@ -137,8 +137,8 @@ describe('runnables', () => {
it('does not display time if no time taken', () => {
start()
- cy.get('.runnable-header span:first').should('have.text', 'foo.js')
- cy.get('.runnable-header span:last').should('not.have.text', '--')
+ cy.get('.runnable-header .runnable-header-file-name').contains('foo.js')
+ cy.get('.runnable-header .duration').should('not.exist')
})
describe('when there are no tests', () => {
@@ -204,11 +204,12 @@ describe('runnables', () => {
})
it('contains name of spec and emits when clicked', () => {
- const selector = '.runnable-header a'
+ const selector = '.runnable-header-file-name'
cy.stub(runner, 'emit').callThrough()
- cy.get(selector).as('spec-title').contains('foo.js')
+ cy.get(selector).as('spec-title').contains('foo.js').realHover()
+ cy.get('.open-in-ide-button').click()
cy.get(selector).click().then(() => {
expect(runner.emit).to.be.calledWith('open:file:unified')
})
diff --git a/packages/reporter/cypress/e2e/shortcuts.cy.ts b/packages/reporter/cypress/e2e/shortcuts.cy.ts
index 4ada861cb4ff..c31c1bb7c39c 100755
--- a/packages/reporter/cypress/e2e/shortcuts.cy.ts
+++ b/packages/reporter/cypress/e2e/shortcuts.cy.ts
@@ -82,17 +82,17 @@ describe('shortcuts', function () {
cy.get('body').then(() => {
expect(runner.emit).not.to.have.been.calledWith('save:state')
- cy.contains('button', 'Specs').should('have.attr', 'aria-expanded', 'false')
+ cy.get('[data-cy=toggle-specs-button]').should('have.attr', 'aria-expanded', 'false')
})
cy.get('body').type('f').then(() => {
expect(runner.emit).to.have.been.calledWith('save:state')
- cy.contains('button', 'Specs').should('have.attr', 'aria-expanded', 'true')
+ cy.get('[data-cy=toggle-specs-button]').should('have.attr', 'aria-expanded', 'true')
})
cy.get('body').type('f').then(() => {
expect(runner.emit).to.have.been.calledWith('save:state')
- cy.contains('button', 'Specs').should('have.attr', 'aria-expanded', 'false')
+ cy.get('[data-cy=toggle-specs-button]').should('have.attr', 'aria-expanded', 'false')
})
})
@@ -140,9 +140,9 @@ describe('shortcuts', function () {
})
it('has shortcut in tooltips', () => {
- cy.get('.toggle-specs-wrapper > button').trigger('mouseover')
+ cy.get('[data-cy=toggle-specs-button]').trigger('mouseover')
cy.get('.cy-tooltip').should('have.text', 'Expand Specs List F')
- cy.get('.toggle-specs-wrapper > button').trigger('mouseout')
+ cy.get('[data-cy=toggle-specs-button]').trigger('mouseout')
cy.get('button.restart').trigger('mouseover')
cy.get('.cy-tooltip').should('have.text', 'Run All Tests R')
diff --git a/packages/reporter/cypress/e2e/spec_title.cy.ts b/packages/reporter/cypress/e2e/spec_title.cy.ts
index 51f89915d69c..938c39044808 100644
--- a/packages/reporter/cypress/e2e/spec_title.cy.ts
+++ b/packages/reporter/cypress/e2e/spec_title.cy.ts
@@ -55,19 +55,24 @@ describe('spec title', () => {
})
it('displays name without path', () => {
- cy.get('.runnable-header').find('a').should('have.text', 'foo.js')
+ cy.get('.runnable-header-file-name').contains('foo.js')
cy.percySnapshot()
})
- it('displays tooltip on hover', () => {
- cy.get('.runnable-header a').first().trigger('mouseover')
- cy.get('.cy-tooltip').first().should('have.text', 'Open in IDE')
+ it('displays Open in IDE button on spec name hover', () => {
+ cy.get('.open-in-ide-button').should('have.css', 'opacity', '0')
+
+ cy.get('.runnable-header-file-name').realHover()
+ cy.get('.open-in-ide-button').should('have.css', 'opacity', '1')
+ cy.get('.open-in-ide-button').contains('Open in IDE')
+
+ cy.percySnapshot()
})
itHandlesFileOpening({
getRunner: () => runner,
- selector: '.runnable-header a',
+ selector: '.open-in-ide-button',
file: {
file: '/absolute/path/to/foo.js',
line: 0,
diff --git a/packages/reporter/cypress/e2e/suites.cy.ts b/packages/reporter/cypress/e2e/suites.cy.ts
index ba91185ab3e7..61144a3eb10f 100644
--- a/packages/reporter/cypress/e2e/suites.cy.ts
+++ b/packages/reporter/cypress/e2e/suites.cy.ts
@@ -56,6 +56,10 @@ describe('suites', () => {
.closest('.runnable')
.should('have.class', 'runnable-failed')
+ cy.contains('suite 1 > nested suite 1')
+ .closest('.runnable')
+ .should('have.class', 'runnable-processing')
+
cy.contains('suite 2')
.closest('.runnable')
.should('have.class', 'runnable-passed')
@@ -148,27 +152,17 @@ describe('suites', () => {
cy.contains('nested suite 1')
.closest('.runnable-wrapper')
.realHover()
- .find('.runnable-controls-studio')
+ .get('[data-cy="create-new-test-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().within(() => {
+ 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/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/e2e/tests.cy.ts b/packages/reporter/cypress/e2e/tests.cy.ts
index b1ba923e33fa..7c97da55ae51 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', () => {
@@ -284,7 +296,7 @@ describe('studio controls', () => {
.realHover()
.find('.runnable-controls-studio')
.should('be.visible')
- .should('have.css', 'opacity', '0.5')
+ .should('have.css', 'opacity', '1')
})
it('displays studio icon with no transparency and tooltip on hover', { scrollBehavior: false }, () => {
@@ -355,13 +367,9 @@ describe('studio controls', () => {
it('is visible without save and copy button if test was skipped', () => {
cy.contains('nested suite 1')
.parents('.collapsible').first()
- .contains('test 1').click()
- .parents('.collapsible').first()
- .find('.studio-controls').as('pendingControls')
- .should('be.visible')
-
- cy.get('@pendingControls').find('.studio-save').should('not.be.visible')
- cy.get('@pendingControls').find('.studio-copy').should('not.be.visible')
+ .contains('test 1').should('have.css', 'pointer-events', 'none')
+ .parents('.collapsible').first().scrollIntoView()
+ .find('.studio-controls').should('not.exist')
})
it('is not visible while test is running', () => {
diff --git a/packages/reporter/cypress/e2e/unit/suite_model.cy.ts b/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
index 8822c98e1dcd..09deb8246009 100644
--- a/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
+++ b/packages/reporter/cypress/e2e/unit/suite_model.cy.ts
@@ -1,10 +1,10 @@
import Suite from '../../../src/runnables/suite-model'
import TestModel from '../../../src/test/test-model'
-const suiteWithChildren = (children: Array>) => {
- const suite = new Suite({ id: '1', title: '', hooks: [] }, 0)
+const suiteWithChildren = (children: Array>) => {
+ const suite = new Suite({ id: '1', title: '', hooks: [], suites: [], tests: [] }, 0)
- suite.children = children as Array
+ suite.children = children.map((child) => ({ type: 'test', ...child })) as Array
return suite
}
@@ -41,22 +41,25 @@ describe('Suite model', () => {
expect(suite.state).to.equal('passed')
})
- it('is processing when all children are active', () => {
+ // TODO: https://github.com/cypress-io/cypress-services/issues/11050
+ it.skip('is active when all children are active', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'active' }])
- expect(suite.state).to.equal('processing')
+ expect(suite.state).to.equal('active')
})
- it('is processing when there are active tests with passing tests', () => {
+ // TODO: https://github.com/cypress-io/cypress-services/issues/11050
+ it.skip('is active when there are active tests with passing tests', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'passed' }])
- expect(suite.state).to.equal('processing')
+ expect(suite.state).to.equal('active')
})
- it('is processing when there are active tests with pending tests', () => {
+ // TODO: https://github.com/cypress-io/cypress-services/issues/11050
+ it.skip('is active when there are active tests with pending tests', () => {
const suite = suiteWithChildren([{ state: 'active' }, { state: 'pending' }])
- expect(suite.state).to.equal('processing')
+ expect(suite.state).to.equal('active')
})
it('is processing when all children are processing', () => {
@@ -77,4 +80,52 @@ describe('Suite model', () => {
expect(suite.state).to.equal('processing')
})
})
+
+ describe('nested suites', () => {
+ it('is passed even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'passed', type: 'test' }, { state: 'active', type: 'suite' }, { state: 'failed', type: 'suite' }])
+
+ expect(suite.state).to.equal('passed')
+ expect(suite.children[0].state).to.equal('passed')
+ expect(suite.children[1].state).to.equal('active')
+ expect(suite.children[2].state).to.equal('failed')
+ })
+
+ it('is failed even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'failed' }, { state: 'passed', type: 'suite' }, { state: 'passed', type: 'suite' }])
+
+ expect(suite.state).to.equal('failed')
+ expect(suite.children[0].state).to.equal('failed')
+ expect(suite.children[1].state).to.equal('passed')
+ expect(suite.children[2].state).to.equal('passed')
+ })
+
+ // TODO: https://github.com/cypress-io/cypress-services/issues/11050
+ it.skip('is active even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'active' }, { state: 'processing', type: 'suite' }, { state: 'passed', type: 'suite' }])
+
+ expect(suite.state).to.equal('active')
+ expect(suite.children[0].state).to.equal('active')
+ expect(suite.children[1].state).to.equal('processing')
+ expect(suite.children[2].state).to.equal('passed')
+ })
+
+ it('is processing even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'processing' }, { state: 'passed', type: 'suite' }, { state: 'pending', type: 'suite' }])
+
+ expect(suite.state).to.equal('processing')
+ expect(suite.children[0].state).to.equal('processing')
+ expect(suite.children[1].state).to.equal('passed')
+ expect(suite.children[2].state).to.equal('pending')
+ })
+
+ it('is pending even when children suites are not', () => {
+ const suite = suiteWithChildren([{ state: 'pending' }, { state: 'passed', type: 'suite' }, { state: 'failed', type: 'suite' }])
+
+ expect(suite.state).to.equal('pending')
+ expect(suite.children[0].state).to.equal('pending')
+ expect(suite.children[1].state).to.equal('passed')
+ expect(suite.children[2].state).to.equal('failed')
+ })
+ })
})
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/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/package.json b/packages/reporter/package.json
index 5c62f5e04cbb..8f21b0ac373d 100644
--- a/packages/reporter/package.json
+++ b/packages/reporter/package.json
@@ -15,6 +15,10 @@
"watch": "yarn build-for-tests --watch --progress"
},
"devDependencies": {
+ "@cypress-design/constants-button": "^1.9.0",
+ "@cypress-design/css": "1.2.0",
+ "@cypress-design/react-button": "^1.10.1",
+ "@cypress-design/react-icon": "^1.27.0",
"@cypress/react-tooltip": "0.5.3",
"@fontsource/mulish": "4.3.0",
"@fontsource/open-sans": "4.3.0",
@@ -24,6 +28,7 @@
"@packages/frontend-shared": "0.0.0-development",
"@packages/types": "0.0.0-development",
"@packages/web-config": "0.0.0-development",
+ "autoprefixer": "10.4.21",
"classnames": "^2.5.1",
"cross-env": "7.0.3",
"css-element-queries": "1.2.3",
@@ -33,11 +38,13 @@
"markdown-it": "^14.0.0",
"mobx": "6.13.6",
"mobx-react": "9.1.1",
+ "postcss": "8.5.6",
"prismjs": "1.27.0",
"prop-types": "15.7.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"sinon": "7.5.0",
+ "tailwindcss": "4.1.10",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4"
},
diff --git a/packages/reporter/postcss.config.js b/packages/reporter/postcss.config.js
new file mode 100644
index 000000000000..33ad091d26d8
--- /dev/null
+++ b/packages/reporter/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/packages/reporter/src/OpenFileInIDEButton.tsx b/packages/reporter/src/OpenFileInIDEButton.tsx
new file mode 100644
index 000000000000..8babe57898f6
--- /dev/null
+++ b/packages/reporter/src/OpenFileInIDEButton.tsx
@@ -0,0 +1,19 @@
+import Button from '@cypress-design/react-button'
+import React from 'react'
+import events from './lib/events'
+import { IconWindowCodeEditor } from '@cypress-design/react-icon'
+import { FileDetails } from '@packages/types'
+import cx from 'classnames'
+
+interface Props {
+ fileDetails: FileDetails
+ className?: string
+}
+
+export const OpenFileInIDEButton = ({ fileDetails, className }: Props) => {
+ return (<>
+
+
+ >
+ )
+}
diff --git a/packages/reporter/src/attempts/attempts.scss b/packages/reporter/src/attempts/attempts.scss
index f88e9ee11762..8ccefd6cbb4b 100644
--- a/packages/reporter/src/attempts/attempts.scss
+++ b/packages/reporter/src/attempts/attempts.scss
@@ -1,40 +1,64 @@
.reporter {
+ // Mixin for dotted border line
+ @mixin dotted-border-line($position: "top") {
+ border-left: 1px dotted $gray-800;
+ content: "";
+ left: 16px;
+ position: absolute;
+ height: 8px;
+ z-index: 1;
+
+ @if $position == "top" {
+ top: 0;
+ } @else if $position == "bottom" {
+ bottom: 0;
+ }
+ }
+
.attempts {
+ border-right: 1px solid $gray-800;
+ border-bottom: 1px solid $gray-800;
+ border-radius: 0 0 4px 4px;
+
.attempt-item > .collapsible > .collapsible-header-wrapper {
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 {
+ @include dotted-border-line("top");
+ }
+ }
+ > .collapsible .attempt-name {
+ &:after {
+ @include dotted-border-line("bottom");
+ }
+ }
}
}
- .attempt-item {
- margin-bottom: 7px;
+ .attempt-error-region {
+ margin: 0 8.5px;
+ }
+ .attempt-item {
> .collapsible {
position: relative;
- margin-right: 16px;
- .collapsible-header-inner {
- outline: none;
- }
- &:before {
- border-left: 1px solid $gray-900;
- content: '';
- left: 9px;
- position: absolute;
- top: 22px;
- height: 15px;
+ > .attempt-name > .collapsible-header {
+ .collapsible-header-inner {
+ outline: none;
+ display: flex;
+ align-items: center;
+ width: 100%;
+ padding: 0;
+ }
}
-
- &.is-open:before {
- display: none;
- }
- }
-
- &:last-child > .collapsible:before {
- display: none;
}
> .is-open .open-close-indicator {
@@ -47,76 +71,60 @@
}
}
- .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;
+ margin-bottom: 6px;
- .attempt-state-failed {
- .attempt-name:after {
- color: $fail;
+ > div {
+ width: 100%;
+ }
}
- }
- .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.20);
- display: flex;
- font-size: 11px;
- padding: 2px 5px;
+ font-size: 14px;
+ gap: 8px;
+ width: 100%;
+ padding: 8px;
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/collapsible/collapsible.scss b/packages/reporter/src/collapsible/collapsible.scss
index 95ed565b95b5..b423ca0835cc 100644
--- a/packages/reporter/src/collapsible/collapsible.scss
+++ b/packages/reporter/src/collapsible/collapsible.scss
@@ -3,10 +3,6 @@
margin-right: 8px;
transform: rotate(-90deg);
transition: transform 150ms ease-out;
-
- .icon-dark {
- stroke: $gray-800;
- }
}
.is-open > .collapsible-header-wrapper > .collapsible-header > .collapsible-header-inner > .collapsible-indicator {
diff --git a/packages/reporter/src/collapsible/collapsible.tsx b/packages/reporter/src/collapsible/collapsible.tsx
index 7c2125a13207..287a5b768dac 100644
--- a/packages/reporter/src/collapsible/collapsible.tsx
+++ b/packages/reporter/src/collapsible/collapsible.tsx
@@ -1,13 +1,19 @@
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'
+import { IconChevronDownSmall } from '@cypress-design/react-icon'
+
+export interface CollapsibleHeaderComponentProps {
+ isOpen: boolean
+}
interface CollapsibleProps {
isOpen?: boolean
headerClass?: string
headerStyle?: CSSProperties
header?: ReactNode
+ HeaderComponent?: React.FunctionComponent
headerExtras?: ReactNode
containerRef?: RefObject
contentClass?: string
@@ -16,7 +22,7 @@ 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 toggleOpenState = useCallback((e?: MouseEvent) => {
@@ -46,9 +52,10 @@ const Collapsible: React.FC = ({ isOpen: isOpenAsProp = false,
style={headerStyle}
tabIndex={-1}
>
- {!hideExpander && }
+ {!hideExpander && headerClass === 'hook-header' && }
+ {!hideExpander && headerClass !== 'hook-header' && }
- {header}
+ {HeaderComponent ? : header}
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/command.tsx b/packages/reporter/src/commands/command.tsx
index 83d813126a53..819102f60fce 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) => (
-
+ // 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}
+
+ )
)
})
Suite.displayName = 'Suite'
export interface RunnableProps {
+ appState?: AppState
model: TestModel | SuiteModel
- appState: AppState
studioEnabled: boolean
canSaveStudioLogs: 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 }) => {
- return (
+const Runnable: React.FC = observer(({ appState: appStateProps = appState, model, studioEnabled, canSaveStudioLogs, shouldShowConnectingDots }) => {
+ return (<>
{model.type === 'test'
?
- : }
+ : }
+ {shouldShowConnectingDots && }
+ >
)
})
diff --git a/packages/reporter/src/runnables/runnable-header.tsx b/packages/reporter/src/runnables/runnable-header.tsx
index b47eac8a3a78..499b0ae6203a 100644
--- a/packages/reporter/src/runnables/runnable-header.tsx
+++ b/packages/reporter/src/runnables/runnable-header.tsx
@@ -3,16 +3,19 @@ import React, { ReactElement } from 'react'
import type { StatsStore } from '../header/stats-store'
import { formatDuration, getFilenameParts } from '../lib/util'
-import FileNameOpener from '../lib/file-name-opener'
+import { RunnablesStore } from './runnables-store'
+import { DebugDismiss } from '../header/DebugDismiss'
+import { OpenFileInIDEButton } from '../OpenFileInIDEButton'
const renderRunnableHeader = (children: ReactElement) =>