Skip to content

Commit

Permalink
feat: show running builds in the Debug page (#25936)
Browse files Browse the repository at this point in the history
* update format for duration less than 1 sec

* Move DebugNewRelevantRunBar above header

* Adding link to switch runs when running

* Update DebugPendingRunSplash

* New DebugTestingProgress component

* Adding DebugTestingProgress to DebugContainer

* Adding test for showing failed tests for running

* Update mutation for moving relevant runs

* Fix typescript

* Type fix

* Fix for Mac OS

* Watch total tests in relevant run specs data source

* Schema change missed earlier

* Adding transitions to UI

* Caching gql results between changes to remove UI flicker

* Correcting application of attributes

* Modify StatsMetadata to incorporate ResultCounts

* Adding transition to width

* Update mountFragment and test to match

* Adding changelog

* Update changelog

* Make use of useIntervalFn

* Add interval to timing display in header

* Rename variable

* Fixing GQL warnings from test

* Adding entry for Chrome Beta

* Update polling behavior for stopping and fix test for changes in RelevantRunSpecsDataSource

* Poller updates to tracking start/stop

* Add scheduled to complete message to run splash

* Update Sidebar badge to support running builds

* fix tracking of completion date in data source

* Updating isLoading logic

* Add missing field to test data

* Update formatting of time remaining

* Test refactoring

* Fixing types

* Update link to show previous

* Update runs after a status change

* Update method documentation

* Update cli/CHANGELOG.md

Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com>

* Remove console.log

* Better checks for numbers

* Rename moveToNext to moveToRun

* Simplify check

Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com>

* Simplify check

* Fixing document name

* Update logic for when to move runs

---------

Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com>
  • Loading branch information
warrensplayer and mike-plummer authored Mar 6, 2023
1 parent a9ab4c7 commit 434e6ee
Show file tree
Hide file tree
Showing 45 changed files with 1,091 additions and 329 deletions.
1 change: 1 addition & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ _Released 03/14/2023 (PENDING)_
**Features:**

- It is now possible to control the number of connection attempts to the browser using the CYPRESS_CONNECT_RETRY_THRESHOLD Environment Variable. Learn more [here](https://docs.cypress.io/guides/references/advanced-installation#Environment-variables). Addressed in [#25848](https://github.com/cypress-io/cypress/pull/25848).
- The Debug page is now able to show real-time results from in-progress runs. Addresses [#25759](https://github.com/cypress-io/cypress/issues/25759).

**Misc:**

Expand Down
1 change: 1 addition & 0 deletions packages/app/cypress/fixtures/debug-Failing/gql-Debug.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"totalFlakyTests": null,
"cancelledBy": null,
"cancelledAt": null,
"scheduledToCompleteAt": null,
"errors": [],
"overLimitActionType": "UPGRADE",
"overLimitActionUrl": "https://cloud.cypress.io/organizations/021fea67-d608-4ab2-af17-3f8a2a23d019/pricing",
Expand Down
1 change: 1 addition & 0 deletions packages/app/cypress/fixtures/debug-Passing/gql-Debug.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"totalFlakyTests": null,
"cancelledBy": null,
"cancelledAt": null,
"scheduledToCompleteAt": null,
"errors": [],
"overLimitActionType": "UPGRADE",
"overLimitActionUrl": "https://cloud.cypress.io/organizations/021fea67-d608-4ab2-af17-3f8a2a23d019/pricing",
Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/composables/useDurationFormat.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ describe('useDurationFormat', () => {

// expects 24 hours and greater to "roll over" and not include day information
expect(useDurationFormat(86400000).value).to.eq('00:00')

// expects values less than 1 sec to show milliseconds
expect(useDurationFormat(456).value).to.eq('456ms')
})

it('should render with value', () => {
Expand Down
10 changes: 9 additions & 1 deletion packages/app/src/composables/useDurationFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,13 @@ import { dayjs } from '../runs/utils/day.js'
Ex: 1 hour and 1 second which is 3601000ms = 01:00:01
*/
export function useDurationFormat (value: number | Ref<number>) {
return computed(() => dayjs.duration(unref(value)).format('HH:mm:ss').replace(/^0+:/, ''))
return computed(() => {
const duration = unref(value)

if (duration >= 1000) {
return dayjs.duration(duration).format('HH:mm:ss').replace(/^0+:/, '')
}

return `${duration }ms`
})
}
156 changes: 136 additions & 20 deletions packages/app/src/debug/DebugContainer.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { DebugSpecListGroupsFragment, DebugSpecListSpecFragment, DebugSpecListTestsFragment, DebugSpecsFragmentDoc, UseCohorts_DetermineCohortDocument } from '../generated/graphql-test'
import { DebugSpecListGroupsFragment, DebugSpecListSpecFragment, DebugSpecListTestsFragment, DebugSpecsFragment, DebugSpecsFragmentDoc, UseCohorts_DetermineCohortDocument } from '../generated/graphql-test'
import DebugContainer from './DebugContainer.vue'
import { defaultMessages } from '@cy/i18n'
import { useLoginConnectStore } from '@packages/frontend-shared/src/store/login-connect-store'
import { specsList } from './utils/DebugMapping'
import { CloudRunStubs } from '@packages/graphql/test/stubCloudTypes'
import { DEBUG_SLIDESHOW } from './utils/constants'
import type { CloudRun, CloudSpecRun, CloudTestResult } from '@packages/graphql/src/gen/test-cloud-graphql-types.gen'

const DebugSpecVariableTypes = {
hasNextRun: 'Boolean',
Expand Down Expand Up @@ -238,7 +239,7 @@ describe('<DebugContainer />', () => {
loginConnectStore.setHasInitiallyLoaded()
})

it('render first pending run', () => {
it('renders running run', () => {
cy.mountFragment(DebugSpecsFragmentDoc, {
variableTypes: DebugSpecVariableTypes,
variables: {
Expand All @@ -262,14 +263,15 @@ describe('<DebugContainer />', () => {
})

cy.findByTestId('debug-header').should('be.visible')
cy.findByTestId('debug-testing-progress').should('be.visible')
cy.findByTestId('debug-pending-splash')
.should('be.visible')
.within(() => {
cy.findByTestId('debug-pending-counts').should('have.text', '0 of 0 specs completed')
cy.contains('Testing in progress...')
})
})

it('does not render DebugPendingRunSplash and DebugNewRelevantRunBar at the same time', () => {
it('renders running run with failed tests', () => {
cy.mountFragment(DebugSpecsFragmentDoc, {
variableTypes: DebugSpecVariableTypes,
variables: {
Expand All @@ -281,37 +283,151 @@ describe('<DebugContainer />', () => {
if (result.currentProject?.cloudProject?.__typename === 'CloudProject') {
const test = result.currentProject.cloudProject.runByNumber

// Testing this to confirm we are "making impossible states impossible" in the UI,
// and document the expectation in this scenario. For clarity,
// we do not expect a 'RUNNING` current and next run at the same time, so
// the data below represents an invalid state.

result.currentProject.cloudProject.runByNumber = {
...CloudRunStubs.running,
...CloudRunStubs.failingWithTests,
status: 'RUNNING',
runNumber: 1,
completedInstanceCount: 2,
totalInstanceCount: 3,
} as typeof test
}
},
render: (gqlVal) => <DebugContainer gql={gqlVal} />,
})

result.currentProject.cloudProject.nextRun = {
...CloudRunStubs.running,
cy.findByTestId('debug-header').should('be.visible')
cy.findByTestId('debug-testing-progress').should('be.visible')
cy.findByTestId('debug-spec-item').should('be.visible')
})

it('simulates full running run with failed tests', () => {
//Change this value when modifying this test to allow time to see transitions
const waitTimeBetweenSimulatedEvents = 0

cy.mountFragment(DebugSpecsFragmentDoc, {
variableTypes: DebugSpecVariableTypes,
variables: {
hasNextRun: false,
runNumber: 1,
nextRunNumber: -1,
},
onResult: (result) => {
if (result.currentProject?.cloudProject?.__typename === 'CloudProject') {
const test = result.currentProject.cloudProject.runByNumber

//creating copy to prevent mutation later on in this test
const cloudRunCopy = JSON.parse(JSON.stringify(CloudRunStubs.failingWithTests))

result.currentProject.cloudProject.runByNumber = {
...cloudRunCopy,
status: 'RUNNING',
runNumber: 1,
completedInstanceCount: 5,
totalInstanceCount: 6,
completedInstanceCount: 2,
totalInstanceCount: 3,
} as typeof test
}
},
render: (gqlVal) => <DebugContainer gql={gqlVal} />,
render: (gqlVal) => {
return <DebugContainer gql={gqlVal} />
},
}).then(({ component }) => {
cy.wrap(component.gql).as('gql')
})

/*
DebugTestingProgress is not mocked here resulting in it always
saying "0 of 0 specs completed"
Trying to mock up the DebugTestingProgress here results in
Urql clearing out and refetching the main query which makes
this test fail.
*/

const getRun = (gql: DebugSpecsFragment) => {
const run = gql.currentProject?.cloudProject?.__typename === 'CloudProject'
&& gql.currentProject.cloudProject.runByNumber

if (!run) {
throw Error('Could not find run')
}

return run
}

cy.findByTestId('debug-header').should('be.visible')
cy.findByTestId('debug-pending-splash')
.should('be.visible')
cy.findByTestId('debug-testing-progress').should('be.visible')

cy.wait(waitTimeBetweenSimulatedEvents)
cy.get<DebugSpecsFragment>('@gql').then((gql) => {
const run = getRun(gql)

cy.wrap(run).as('run')

run.totalFailed = 4
const newTest = JSON.parse(JSON.stringify(run.testsForReview[0]))

newTest.id = '345'
newTest.thumbprint = `${newTest.thumbprint}c`

run.testsForReview.push(newTest)
})

cy.wait(waitTimeBetweenSimulatedEvents)
cy.findAllByTestId('debug-spec-item').should('have.length', 1)
cy.get<CloudRun>('@run').then((run) => {
const newSpec: CloudSpecRun = JSON.parse(JSON.stringify(run.specs[0]))

newSpec.id = 'spec2'
run.specs.push(newSpec)
cy.wrap(newSpec).as('newSpec')

const newSpecTest: CloudTestResult = JSON.parse(JSON.stringify(run.testsForReview[0]))

newSpecTest.id = '789'
newSpecTest.thumbprint = `${newSpecTest.thumbprint}d`
newSpecTest.specId = newSpec.id
run.testsForReview.push(newSpecTest)

cy.wrap(newSpecTest).as('newSpecTest')
})

cy.wait(waitTimeBetweenSimulatedEvents)
cy.findAllByTestId('debug-spec-item').should('have.length', 2)
cy.get<CloudRun>('@run').then((run) => {
const newGroup = JSON.parse(JSON.stringify(run.groups[0]))

newGroup.id = 'Group2'
newGroup.groupName = 'Group-Linux-Electron'
newGroup.os.name = 'Linux'
newGroup.os.platform = 'LINUX'
newGroup.os.version = '16'
newGroup.os.nameWithVersion = 'Linux 16'
run.groups.push(newGroup)

cy.get<CloudSpecRun>('@newSpec').then((newSpec) => {
newSpec.groupIds!.push(newGroup.id)

cy.get<CloudTestResult>('@newSpecTest').then((newSpecTest) => {
const newGroupTest = JSON.parse(JSON.stringify(newSpecTest))

newGroupTest.instance.groupId = newGroup.id

run.testsForReview.push(newGroupTest)
})
})
})

cy.findAllByTestId('debug-spec-item').should('have.length', 2)
cy.get(':nth-child(2) > [data-cy="debug-spec-item"] > [data-cy="test-group"] > [data-cy="debug-failed-test-groups"]')
.within(() => {
cy.findByTestId('debug-pending-counts').should('have.text', '0 of 0 specs completed')
cy.findAllByTestId('grouped-row').should('have.length', 2)
})

cy.wait(waitTimeBetweenSimulatedEvents)
cy.get<CloudRun>('@run').then((run) => {
run.status = 'FAILED'
})

cy.findByTestId('newer-relevant-run').should('not.exist')
cy.findByTestId('debug-testing-progress').should('not.exist')
})

it('renders specs and tests when completed run available', () => {
Expand Down Expand Up @@ -423,7 +539,7 @@ describe('<DebugContainer />', () => {
cy.findByTestId('newer-relevant-run')
.should('be.visible')
.and('contain.text', 'fix: make gql work FAILED')
.and('contain.text', 'View run')
.and('contain.text', 'Switch to run')
})
})
})
Expand Down
28 changes: 19 additions & 9 deletions packages/app/src/debug/DebugContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,25 @@
/>
<div
v-else-if="run?.status"
class="flex flex-col h-full"
class="flex flex-col h-full p-1.5rem gap-24px"
>
<DebugNewRelevantRunBar
v-if="nextRelevantRun"
:gql="nextRelevantRun"
:current-run-number="run.runNumber"
/>
<DebugPageHeader
:gql="run"
:commits-ahead="props.commitsAhead"
/>
<TransitionQuickFade>
<DebugTestingProgress v-if="isRunning" />
</TransitionQuickFade>
<DebugPendingRunSplash
v-if="isFirstPendingRun"
v-if="isRunning && !run.totalFailed"
class="mt-12"
/>
<DebugNewRelevantRunBar
v-else-if="newerRelevantRun"
:gql="newerRelevantRun"
:is-completion-scheduled="isScheduledToComplete"
/>
<template v-else>
Expand Down Expand Up @@ -75,6 +81,7 @@ import NoInternetConnection from '@packages/frontend-shared/src/components/NoInt
import DebugLoading from '../debug/empty/DebugLoading.vue'
import DebugPageHeader from './DebugPageHeader.vue'
import DebugPendingRunSplash from './DebugPendingRunSplash.vue'
import DebugTestingProgress from './DebugTestingProgress.vue'
import DebugSpecList from './DebugSpecList.vue'
import DebugPageDetails from './DebugPageDetails.vue'
import DebugNotLoggedIn from './empty/DebugNotLoggedIn.vue'
Expand Down Expand Up @@ -116,6 +123,7 @@ fragment DebugSpecs on Query {
email
}
cancelledAt
scheduledToCompleteAt
id
runNumber
errors
Expand Down Expand Up @@ -197,7 +205,7 @@ function shouldDisplayDetails (status: CloudRunStatus, isHidden: boolean) {
}
function shouldDisplaySpecsList (status: CloudRunStatus) {
return ['ERRORED', 'CANCELLED', 'TIMEDOUT', 'FAILED'].includes(status)
return ['ERRORED', 'CANCELLED', 'TIMEDOUT', 'FAILED', 'RUNNING'].includes(status)
}
const debugSpecsArray = computed(() => {
Expand All @@ -221,9 +229,11 @@ const debugSpecsArray = computed(() => {
return []
})
const newerRelevantRun = computed(() => nextRun.value)
const nextRelevantRun = computed(() => nextRun.value)
const isRunning = computed(() => !!run.value && run.value.status === 'RUNNING')
const isFirstPendingRun = computed(() => run.value && run.value.status === 'RUNNING')
const isScheduledToComplete = computed(() => !!run.value?.scheduledToCompleteAt)
const reasonsRunIsHidden = computed(() => (run.value?.reasonsRunIsHidden || []) as CloudRunHidingReason[])
Expand Down
22 changes: 13 additions & 9 deletions packages/app/src/debug/DebugFailedTest.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,22 @@
</div>
</div>
</div>
<div
v-if="props.expandable"
class="divide-y rounded border-gray-100 border-1"
>
<GroupedDebugFailedTestVue
:failed-tests="props.failedTestsResult"
:groups="props.groups"
/>
</div>
<TransitionQuickFade>
<div
v-if="props.expandable"
data-cy="debug-failed-test-groups"
class="divide-y rounded border-gray-100 border-1"
>
<GroupedDebugFailedTestVue
:failed-tests="props.failedTestsResult"
:groups="props.groups"
/>
</div>
</TransitionQuickFade>
</template>
<script lang="ts" setup>
import { IconChevronRightSmall } from '@cypress-design/vue-icon'
import TransitionQuickFade from '@cy/components/transitions/TransitionQuickFade.vue'
import { SolidStatusIcon } from '@cypress-design/vue-statusicon'
import DebugArtifactLink from './DebugArtifactLink.vue'
import GroupedDebugFailedTestVue from './GroupedDebugFailedTest.vue'
Expand Down
Loading

5 comments on commit 434e6ee

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 434e6ee Mar 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.8.0/linux-arm64/develop-434e6eec6e54461041774059b2d4ef5143b56a3d/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 434e6ee Mar 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.8.0/linux-x64/develop-434e6eec6e54461041774059b2d4ef5143b56a3d/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 434e6ee Mar 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.8.0/darwin-arm64/develop-434e6eec6e54461041774059b2d4ef5143b56a3d/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 434e6ee Mar 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.8.0/darwin-x64/develop-434e6eec6e54461041774059b2d4ef5143b56a3d/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 434e6ee Mar 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.8.0/win32-x64/develop-434e6eec6e54461041774059b2d4ef5143b56a3d/cypress.tgz

Please sign in to comment.