)
- cy.contains('button', 'Connect your project').should('be.visible')
+ cy.contains('button', 'Connect a Cypress Cloud project').should('be.visible')
})
it('uses the store to open the Login Connect modal', () => {
loginConnectStore.openLoginConnectModal = cy.spy().as('openLoginConnectModal')
cy.mount(() =>
@@ -39,7 +41,7 @@ import DebugPassed from './DebugPassed.vue'
import DebugErrored from './DebugErrored.vue'
import DebugNoTests from './DebugNoTests.vue'
import DebugTimedout from './DebugTimedout.vue'
-import DebugOverLimit from './DebugOverLimit.vue'
+import DebugOverLimit, { CloudRunHidingReason } from './DebugOverLimit.vue'
gql`
fragment DebugPageDetails_cloudCiBuildInfo on CloudCiBuildInfo {
@@ -59,12 +61,14 @@ const props = defineProps<{
email?: string | null
} | null
}
- isHiddenByUsageLimits: boolean
+ isHidden: boolean
+ reasonsRunIsHidden: (CloudRunHidingReason | null)[]
overLimitActionType: OverLimitActionTypeEnum
overLimitActionUrl: string
specs: readonly DebugSpecListSpecFragment[]
ci?: DebugPageDetails_CloudCiBuildInfoFragment
errors: readonly string[]
+ runAgeDays: number
}>()
const totalSkippedSpecs = computed(() => {
diff --git a/packages/app/src/debug/DebugRunStates.cy.tsx b/packages/app/src/debug/DebugRunStates.cy.tsx
index a3dc8a55ad60..81a740df5475 100644
--- a/packages/app/src/debug/DebugRunStates.cy.tsx
+++ b/packages/app/src/debug/DebugRunStates.cy.tsx
@@ -73,20 +73,93 @@ describe('Debug page states', () => {
})
context('over limit', () => {
- it('renders type CONTACT_ADMIN', () => {
- cy.mount()
-
- cy.findByRole('link', { name: 'Contact admin' }).should('be.visible')
-
- cy.percySnapshot()
+ context('Usage Exceeded', () => {
+ it('displays messaging for users', () => {
+ cy.mount(
+ ,
+ )
+
+ cy.percySnapshot()
+ })
+
+ it('displays messaging for plan admins', () => {
+ cy.mount(
+ ,
+ )
+
+ cy.percySnapshot()
+ })
})
- it('renders type UPGRADE', () => {
- cy.mount()
-
- cy.findByRole('link', { name: 'Upgrade plan' }).should('be.visible')
+ context('Retention Exceeded', () => {
+ it('displays messaging for users', () => {
+ cy.mount(
+ ,
+ )
+
+ cy.percySnapshot()
+ })
+
+ it('displays messaging for plan admins', () => {
+ cy.mount(
+ ,
+ )
+
+ cy.percySnapshot()
+ })
+ })
- cy.percySnapshot()
+ context('both usage and retention exceeded', () => {
+ it('selects usage exceeded and displays appropriate message', () => {
+ cy.mount(
+ ,
+ )
+
+ cy.percySnapshot()
+ })
})
})
diff --git a/packages/frontend-shared/src/locales/en-US.json b/packages/frontend-shared/src/locales/en-US.json
index 335c0b307337..40f70fac3534 100644
--- a/packages/frontend-shared/src/locales/en-US.json
+++ b/packages/frontend-shared/src/locales/en-US.json
@@ -651,11 +651,15 @@
"switchTestingTypeAction": "Switch to {testingType} testing"
},
"viewRun": "View run",
- "overPlanLimit": "Over plan limit",
- "reachedMonthlyUsage": "You've reached the monthly usage limit for your billing plan.",
- "upgradeYourPlan": "Upgrade your plan to continue recording runs.",
- "upgradePlan": "Upgrade plan",
- "contactAdmin": "Contact admin",
+ "overLimit": {
+ "usageExceededTitle": "You've reached your monthly test result limit",
+ "usageExceededUserMessage": "Your Free Cypress Cloud plan includes {numberTests} monthly recorded test results. Contact your Cypress Cloud admin to upgrade your plan and view more test results.",
+ "usageExceededAdminMessage": "Your Free Cypress Cloud plan includes {numberTests} monthly recorded test results. Upgrade your plan now to view more test results.",
+ "retentionExceededTitle": "Beyond data retention",
+ "retentionExceededMessage": "Your data retention limit is {limitDays} days and these tests ran {runAgeDays} days ago. Upgrade your plan to increase your data retention limit.",
+ "upgradePlan": "Upgrade plan",
+ "contactAdmin": "Contact admin"
+ },
"wellDone": "Well Done!",
"allYourTestsPassed": "All your tests passed.",
"incomplete": "Incomplete",
diff --git a/packages/graphql/schemas/cloud.graphql b/packages/graphql/schemas/cloud.graphql
index 1bf36c2d38a6..2d9a48b6359c 100644
--- a/packages/graphql/schemas/cloud.graphql
+++ b/packages/graphql/schemas/cloud.graphql
@@ -529,19 +529,24 @@ type CloudRun implements Node {
id: ID!
"""
- Whether this run is hidden by usage limits
+ Whether this run is hidden to the user due to data limits. Specific reasons are provided in the reasonsRunIsHidden field.
"""
- isHiddenByUsageLimits: Boolean!
+ isHidden: Boolean!
"""
- What to do when the run is over the limit
+ Action user can perform when the run is over a usage limit
"""
overLimitActionType: OverLimitActionTypeEnum!
"""
- A link to upgrade or contact an admin
+ A link a user can navigate to when the run is over a usage limit
"""
overLimitActionUrl: String!
+
+ """
+ Reasons why this run is hidden. List will be empty if the run is not hidden.
+ """
+ reasonsRunIsHidden: [CloudRunHidingReason]!
runNumber: Int
"""
@@ -724,6 +729,11 @@ enum CloudRunGroupStatusEnum {
UNCLAIMED
}
+"""
+The reason a run was hidden, along with any details
+"""
+union CloudRunHidingReason = DataRetentionLimitExceeded | UsageLimitExceeded
+
"""
An instance of executing a single test within a run
"""
@@ -1078,6 +1088,16 @@ type CloudUser implements Node {
userIsViewer: Boolean!
}
+"""
+A run was hidden because it was over the data retention limit
+"""
+type DataRetentionLimitExceeded {
+ """
+ The number of days of data retention
+ """
+ dataRetentionDays: Int
+}
+
"""
A date string, such as 2007-12-03, compliant with the `full-date` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.
"""
@@ -1272,3 +1292,13 @@ type SpecDataAggregate {
"""
min: Int
}
+
+"""
+A run was hidden because it was over the usage limit
+"""
+type UsageLimitExceeded {
+ """
+ The number of tests allowed per month
+ """
+ monthlyTests: Int
+}
diff --git a/packages/graphql/schemas/schema.graphql b/packages/graphql/schemas/schema.graphql
index d3fee9d8a5a7..b175603605be 100644
--- a/packages/graphql/schemas/schema.graphql
+++ b/packages/graphql/schemas/schema.graphql
@@ -432,14 +432,21 @@ type CloudRun implements Node {
"""Globally unique identifier representing a concrete GraphQL ObjectType"""
id: ID!
- """Whether this run is hidden by usage limits"""
- isHiddenByUsageLimits: Boolean!
+ """
+ Whether this run is hidden to the user due to data limits. Specific reasons are provided in the reasonsRunIsHidden field.
+ """
+ isHidden: Boolean!
- """What to do when the run is over the limit"""
+ """Action user can perform when the run is over a usage limit"""
overLimitActionType: OverLimitActionTypeEnum!
- """A link to upgrade or contact an admin"""
+ """A link a user can navigate to when the run is over a usage limit"""
overLimitActionUrl: String!
+
+ """
+ Reasons why this run is hidden. List will be empty if the run is not hidden.
+ """
+ reasonsRunIsHidden: [CloudRunHidingReason]!
runNumber: Int
"""All specs within this run"""
@@ -568,6 +575,9 @@ enum CloudRunGroupStatusEnum {
UNCLAIMED
}
+"""The reason a run was hidden, along with any details"""
+union CloudRunHidingReason = DataRetentionLimitExceeded | UsageLimitExceeded
+
"""An instance of executing a single test within a run"""
type CloudRunInstance implements Node {
"""The ID of the group that this instance belongs to"""
@@ -972,6 +982,12 @@ type CurrentProject implements Node & ProjectLike {
title: String!
}
+"""A run was hidden because it was over the data retention limit"""
+type DataRetentionLimitExceeded {
+ """The number of days of data retention"""
+ dataRetentionDays: Int
+}
+
"""
A date string, such as 2007-12-03, compliant with the `full-date` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.
"""
@@ -2162,6 +2178,12 @@ type TestingTypeInfo implements Node {
type: TestingTypeEnum!
}
+"""A run was hidden because it was over the usage limit"""
+type UsageLimitExceeded {
+ """The number of tests allowed per month"""
+ monthlyTests: Int
+}
+
"""Version of Cypress and release date"""
type Version {
"""unique id"""
diff --git a/packages/graphql/test/stubCloudTypes.ts b/packages/graphql/test/stubCloudTypes.ts
index 9bea6d79635d..d7352b5a6f10 100644
--- a/packages/graphql/test/stubCloudTypes.ts
+++ b/packages/graphql/test/stubCloudTypes.ts
@@ -195,7 +195,8 @@ export function createCloudRun (config: Partial): Required {
id: 'ci_id',
},
groups: [],
- isHiddenByUsageLimits: false,
+ isHidden: false,
+ reasonsRunIsHidden: [],
overLimitActionType: 'UPGRADE',
overLimitActionUrl: '',
specs: [],
@@ -370,7 +371,8 @@ export const CloudRunStubs = {
noTests: createCloudRun({ status: 'NOTESTS' }),
timedOutWithCi: createCloudRun({ status: 'TIMEDOUT', ci: { id: 'abc123', formattedProvider: 'Circle CI', ciBuildNumberFormatted: '1234', url: 'https://circleci.com', __typename: 'CloudCiBuildInfo' }, specs: skippedSpecs }),
timedOutWithoutCi: createCloudRun({ status: 'TIMEDOUT', specs: skippedSpecs }),
- overLimit: createCloudRun({ status: 'OVERLIMIT', overLimitActionType: 'CONTACT_ADMIN', overLimitActionUrl: 'http://localhost:3000' }),
+ overLimit: createCloudRun({ status: 'OVERLIMIT', overLimitActionType: 'CONTACT_ADMIN', overLimitActionUrl: 'http://localhost:3000', isHidden: true, reasonsRunIsHidden: [{ __typename: 'UsageLimitExceeded', monthlyTests: 100 }] }),
+ overLimitRetention: createCloudRun({ status: 'OVERLIMIT', overLimitActionType: 'CONTACT_ADMIN', overLimitActionUrl: 'http://localhost:3000', isHidden: true, reasonsRunIsHidden: [{ __typename: 'DataRetentionLimitExceeded', dataRetentionDays: 10 }] }),
cancelled: createCloudRun({ status: 'CANCELLED', cancelledAt: '2019-01-25T02:00:00.000Z', specs: skippedSpecs, cancelledBy: { id: '123', fullName: 'Test Tester', email: 'adams@cypress.io', __typename: 'CloudUser', userIsViewer: true } }),
} as Record>
From c33ba3000353ae3c2ede3bfd785d32a5c6869be3 Mon Sep 17 00:00:00 2001
From: Mark Noonan
Date: Fri, 6 Jan 2023 09:50:55 -0500
Subject: [PATCH 12/40] feat: IATR-M0 Page Header (#24722) (#25360)
Closes undefined
---
packages/app/src/debug/DebugFailedTest.cy.tsx | 5 +-
packages/app/src/debug/DebugFailedTest.vue | 92 +++++++++++++------
2 files changed, 69 insertions(+), 28 deletions(-)
diff --git a/packages/app/src/debug/DebugFailedTest.cy.tsx b/packages/app/src/debug/DebugFailedTest.cy.tsx
index 9d778318e27d..bee1baaced66 100644
--- a/packages/app/src/debug/DebugFailedTest.cy.tsx
+++ b/packages/app/src/debug/DebugFailedTest.cy.tsx
@@ -175,7 +175,7 @@ describe('', () => {
cy.percySnapshot()
})
- it('tests responsvie UI', { viewportWidth: 700 }, () => {
+ it('tests responsive UI', { viewportWidth: 700 }, () => {
const testResult: TestResults = {
id: '676df87874',
titleParts: ['Test content', 'Test content 2', 'Test content 3', 'Test content 4', 'onMount() should be called once', 'hook() should be called twice and then'],
@@ -197,6 +197,9 @@ describe('', () => {
assertRowContents(testResult)
+ cy.contains('...').realHover()
+ cy.contains('[data-cy=tooltip-content]', 'Test content 2 > Test content 3 > Test content 4').should('be.visible')
+
cy.percySnapshot()
})
})
diff --git a/packages/app/src/debug/DebugFailedTest.vue b/packages/app/src/debug/DebugFailedTest.vue
index b7659c16f996..55c93feb7428 100644
--- a/packages/app/src/debug/DebugFailedTest.vue
+++ b/packages/app/src/debug/DebugFailedTest.vue
@@ -1,7 +1,7 @@
)
@@ -169,13 +175,15 @@ describe('SidebarNavigation', () => {
it('renders failure badge when failing tests and abnormal status', () => {
for (const status of ['CANCELLED', 'ERRORED', 'OVERLIMIT', 'TIMEDOUT'] as CloudRunStatus[]) {
+ cy.log(status)
mountComponent({ cloudProject: { status, numFailedTests: 4 } })
- cy.findByLabelText('Relevant run had 4 test failures').should('be.visible').contains('4')
+ cy.findByLabelText('Relevant run had an error with 4 test failures').should('be.visible').contains('4')
}
})
it('renders error badge when no tests and abnormal status', () => {
for (const status of ['CANCELLED', 'ERRORED', 'OVERLIMIT', 'TIMEDOUT'] as CloudRunStatus[]) {
+ cy.log(status)
mountComponent({ cloudProject: { status, numFailedTests: 0 } })
cy.findByLabelText('Relevant run had an error').should('be.visible').contains('0')
}
@@ -189,5 +197,13 @@ describe('SidebarNavigation', () => {
mountComponent({ isLoading: true })
cy.findByLabelText('New Debug feature').should('not.exist')
})
+
+ it('renders new badge if offline', () => {
+ cy.clock(IATR_RELEASE)
+
+ mountComponent({ online: false })
+
+ cy.findByLabelText('New Debug feature').should('be.visible').contains('New')
+ })
})
})
diff --git a/packages/app/src/navigation/SidebarNavigation.vue b/packages/app/src/navigation/SidebarNavigation.vue
index 16555679817f..238fada5e231 100644
--- a/packages/app/src/navigation/SidebarNavigation.vue
+++ b/packages/app/src/navigation/SidebarNavigation.vue
@@ -114,7 +114,7 @@ import { isAllowedFeature } from '@packages/frontend-shared/src/utils/isAllowedF
const { t } = useI18n()
gql`
-fragment SidebarNavigation on Query {
+fragment SidebarNavigation_Settings on Query {
localSettings {
preferences {
isSideNavigationOpen
@@ -124,19 +124,22 @@ fragment SidebarNavigation on Query {
specListWidth
}
}
+}
+`
+
+gql`
+fragment SidebarNavigation on Query {
+ ...SidebarNavigation_Settings
currentProject {
id
cloudProject {
__typename
... on CloudProject {
id
- runByNumber(runNumber: 1) {
+ runByNumber(runNumber: $runNumber) @include(if: $hasCurrentRun){
id
status
- testsForReview {
- id
- state
- }
+ totalFailed
}
}
}
@@ -148,11 +151,15 @@ fragment SidebarNavigation on Query {
gql`
mutation SideBarNavigation_SetPreferences ($value: String!) {
setPreferences (value: $value, type: global) {
- ...SidebarNavigation
+ ...SidebarNavigation_Settings
}
}`
-const props = defineProps<{ gql: SidebarNavigationFragment | undefined, isLoading: boolean }>()
+const props = defineProps<{
+ gql: SidebarNavigationFragment | undefined
+ isLoading: boolean
+ online: boolean
+}>()
const NAV_EXPAND_MIN_SCREEN_WIDTH = 1024
@@ -166,8 +173,11 @@ const debugBadge = computed(() => {
const showNewBadge = isAllowedFeature('debugNewBadge', loginConnectStore)
const newBadge: Badge = { value: t('sidebar.debug.new'), status: 'success', label: t('sidebar.debug.debugFeature') }
- if (props.gql?.currentProject?.cloudProject?.__typename === 'CloudProject') {
- const { status, testsForReview } = props.gql.currentProject.cloudProject.runByNumber || {}
+ if (props.gql?.currentProject?.cloudProject?.__typename === 'CloudProject'
+ && props.gql.currentProject.cloudProject.runByNumber
+ && props.online
+ ) {
+ const { status, totalFailed } = props.gql.currentProject.cloudProject.runByNumber || {}
if (status === 'NOTESTS' || status === 'RUNNING') {
return showNewBadge ? newBadge : undefined
@@ -177,17 +187,27 @@ const debugBadge = computed(() => {
return { value: '0', status: 'success', label: t('sidebar.debug.passed') }
}
- if (testsForReview?.length) {
+ let countToDisplay = '0'
+
+ if (totalFailed) {
+ countToDisplay = totalFailed < 9
+ ? String(totalFailed)
+ : '9+'
+ }
+
+ if (status === 'FAILED') {
return {
- value: testsForReview.length < 9
- ? String(testsForReview.length)
- : '9+',
+ value: countToDisplay,
status: 'failed',
- label: t('sidebar.debug.failed', testsForReview.length),
+ label: t('sidebar.debug.failed', totalFailed || 0),
}
}
- return { value: '0', status: 'error', label: t('sidebar.debug.errored') }
+ const errorLabel = totalFailed && totalFailed > 0
+ ? t('sidebar.debug.erroredWithFailures', totalFailed)
+ : t('sidebar.debug.errored')
+
+ return { value: countToDisplay, status: 'error', label: errorLabel }
}
return showNewBadge ? newBadge : undefined
diff --git a/packages/app/src/navigation/SidebarNavigationContainer.vue b/packages/app/src/navigation/SidebarNavigationContainer.vue
index 34f5d74d5431..5b29eec63663 100644
--- a/packages/app/src/navigation/SidebarNavigationContainer.vue
+++ b/packages/app/src/navigation/SidebarNavigationContainer.vue
@@ -1,20 +1,48 @@
diff --git a/packages/app/src/pages/Debug.vue b/packages/app/src/pages/Debug.vue
index c29d53230250..c4e8df3aefb5 100644
--- a/packages/app/src/pages/Debug.vue
+++ b/packages/app/src/pages/Debug.vue
@@ -1,18 +1,24 @@
-
diff --git a/packages/app/src/runner/unifiedRunner.ts b/packages/app/src/runner/unifiedRunner.ts
index 628625266f5a..5ac68beadec3 100644
--- a/packages/app/src/runner/unifiedRunner.ts
+++ b/packages/app/src/runner/unifiedRunner.ts
@@ -10,8 +10,8 @@ import { gql, useMutation } from '@urql/vue'
import { TestsForRunDocument } from '../generated/graphql'
gql`
-mutation TestsForRun ($runId: String!) {
- testsForRun (runId: $runId)
+mutation TestsForRun ($spec: String!) {
+ testsForRun (spec: $spec)
}
`
@@ -61,8 +61,8 @@ export function useUnifiedRunner () {
return specStore.setActiveSpec(null)
}
- if (route.query.runId) {
- const res = await testsForRunMutation.executeMutation({ runId: route.query.runId as string })
+ if (route.query.mode && route.query.mode === 'debug') {
+ const res = await testsForRunMutation.executeMutation({ spec: activeSpecInSpecsList.relative })
specStore.setTestFilter(res.data?.testsForRun?.length ? res.data.testsForRun : undefined)
} else {
diff --git a/packages/app/src/runner/useEventManager.ts b/packages/app/src/runner/useEventManager.ts
index ca97099cf646..1ef7cd72a603 100644
--- a/packages/app/src/runner/useEventManager.ts
+++ b/packages/app/src/runner/useEventManager.ts
@@ -64,7 +64,7 @@ export function useEventManager () {
eventManager.on('testFilter:cloudDebug:dismiss', () => {
const currentRoute = router.currentRoute.value
- const { runId, ...query } = currentRoute.query
+ const { mode, ...query } = currentRoute.query
// Delete runId from query which will remove the test filter and trigger a rerun
router.replace({ ...currentRoute, query })
diff --git a/packages/data-context/src/data/coreDataShape.ts b/packages/data-context/src/data/coreDataShape.ts
index 8527b75c398c..8f6c66e85c42 100644
--- a/packages/data-context/src/data/coreDataShape.ts
+++ b/packages/data-context/src/data/coreDataShape.ts
@@ -114,7 +114,7 @@ interface Diagnostics {
}
interface CloudDataShape {
- testsForRunResults?: string[]
+ testsForRunResults?: Record
}
export interface CoreDataShape {
@@ -224,9 +224,8 @@ export function makeCoreData (modeOptions: Partial = {}): CoreDa
packageManager: 'npm',
forceReconfigureProject: null,
versionData: null,
- // TODO: Replace stubbed data with real data from cloud
cloud: {
- testsForRunResults: ['t1', 't2', 's1 t3', 's1 t4'],
+ testsForRunResults: {},
},
}
}
diff --git a/packages/graphql/schemas/schema.graphql b/packages/graphql/schemas/schema.graphql
index 5e6a63d7e109..9d91b87895cd 100644
--- a/packages/graphql/schemas/schema.graphql
+++ b/packages/graphql/schemas/schema.graphql
@@ -994,9 +994,6 @@ type CurrentProject implements Node & ProjectLike {
"""A list of specs for the currently open testing type of a project"""
specs: [Spec!]!
-
- """"""
- testsForReviewBySpec(specTitle: String!): [String!]
title: String!
}
@@ -1722,9 +1719,17 @@ type Mutation {
"""List of specs to run for the "Run All Specs" Feature"""
setRunAllSpecs(runAllSpecs: [String!]!): Boolean
+ """Set failed tests for the current run to be used by the runner"""
+ setTestsForRun(testsBySpec: [TestsBySpecInput!]!): Boolean
+
"""Switch Testing type and relaunch browser"""
switchTestingTypeAndRelaunch(testingType: TestingTypeEnum!): Boolean
- testsForRun(runId: String!): [String!]
+
+ """Return the set of test titles for the given spec path"""
+ testsForRun(
+ """Spec path relative to the project"""
+ spec: String!
+ ): [String!]
"""Updates the different fields of the wizard data store"""
wizardUpdate(input: WizardUpdateInput!): Wizard
@@ -2252,6 +2257,17 @@ type TestingTypeInfo implements Node {
type: TestingTypeEnum!
}
+"""
+Represents the input for setting a mapping of test titles by the spec path
+"""
+input TestsBySpecInput {
+ """Path to the spec relative to the project"""
+ specPath: String!
+
+ """Full test title which should be all parts joined by a space"""
+ tests: [String!]!
+}
+
"""A run was hidden because it was over the usage limit"""
type UsageLimitExceeded {
"""The number of tests allowed per month"""
diff --git a/packages/graphql/src/schemaTypes/inputTypes/gql-TestsBySpecsInput.ts b/packages/graphql/src/schemaTypes/inputTypes/gql-TestsBySpecsInput.ts
new file mode 100644
index 000000000000..7e2eeb53109e
--- /dev/null
+++ b/packages/graphql/src/schemaTypes/inputTypes/gql-TestsBySpecsInput.ts
@@ -0,0 +1,15 @@
+import { inputObjectType } from 'nexus'
+
+export const TestsBySpecInput = inputObjectType({
+ name: 'TestsBySpecInput',
+ description: 'Represents the input for setting a mapping of test titles by the spec path',
+ definition (t) {
+ t.nonNull.string('specPath', {
+ description: 'Path to the spec relative to the project',
+ })
+
+ t.nonNull.list.nonNull.string('tests', {
+ description: 'Full test title which should be all parts joined by a space',
+ })
+ },
+})
diff --git a/packages/graphql/src/schemaTypes/inputTypes/index.ts b/packages/graphql/src/schemaTypes/inputTypes/index.ts
index 176455db2187..a2bb0dfe445e 100644
--- a/packages/graphql/src/schemaTypes/inputTypes/index.ts
+++ b/packages/graphql/src/schemaTypes/inputTypes/index.ts
@@ -2,4 +2,5 @@
// created by autobarrel, do not modify directly
export * from './gql-FileDetailsInput'
+export * from './gql-TestsBySpecsInput'
export * from './gql-WizardUpdateInput'
diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-CurrentProject.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-CurrentProject.ts
index dd7d965f71b6..87f300a79255 100644
--- a/packages/graphql/src/schemaTypes/objectTypes/gql-CurrentProject.ts
+++ b/packages/graphql/src/schemaTypes/objectTypes/gql-CurrentProject.ts
@@ -259,17 +259,6 @@ export const CurrentProject = objectType({
return ctx.relevantRunSpecs.specs
},
})
-
- //TODO: Finish implementing resolver for this field to supply runner with tests names to use for filtering
- t.list.nonNull.string('testsForReviewBySpec', {
- description: '',
- args: {
- specTitle: nonNull(stringArg()),
- },
- resolve: (source, args, ctx) => {
- return ['foo/bar']
- },
- })
},
sourceType: {
module: '@packages/data-context/src/data/ProjectLifecycleManager',
diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
index 261b758a002b..9d2a07a38b70 100644
--- a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
+++ b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
@@ -13,6 +13,7 @@ import { ScaffoldedFile } from './gql-ScaffoldedFile'
import { WIZARD_BUNDLERS, WIZARD_FRAMEWORKS } from '@packages/scaffold-config'
import debugLib from 'debug'
import { ReactComponentResponse } from './gql-ReactComponentResponse'
+import { TestsBySpecInput } from '../inputTypes'
const debug = debugLib('cypress:graphql:mutation')
@@ -774,13 +775,40 @@ export const mutation = mutationType({
},
})
- // TODO: replace stub with cloud query
+ //Using a mutation to just return data in order to be able to await the results in the component
t.list.nonNull.string('testsForRun', {
+ description: 'Return the set of test titles for the given spec path',
args: {
- runId: nonNull(stringArg()),
+ spec: nonNull(stringArg({
+ description: 'Spec path relative to the project',
+ })),
},
resolve: (source, args, ctx) => {
- return ctx.coreData.cloud.testsForRunResults || []
+ if (!ctx.coreData.cloud.testsForRunResults) {
+ return []
+ }
+
+ const testsForSpec = ctx.coreData.cloud.testsForRunResults[args.spec]
+
+ return testsForSpec || []
+ },
+ })
+
+ t.boolean('setTestsForRun', {
+ description: 'Set failed tests for the current run to be used by the runner',
+ args: {
+ testsBySpec: nonNull(list(nonNull(arg({
+ type: TestsBySpecInput,
+ })))),
+ },
+ resolve: (source, args, ctx) => {
+ ctx.coreData.cloud.testsForRunResults = args.testsBySpec.reduce<{[index: string]: string[]}>((acc, spec) => {
+ acc[spec.specPath] = spec.tests
+
+ return acc
+ }, {})
+
+ return true
},
})
},
From aa82ddfb459fb55a674ce0b8176f946421b8a44c Mon Sep 17 00:00:00 2001
From: Stokes Player
Date: Wed, 18 Jan 2023 07:50:36 -0500
Subject: [PATCH 18/40] Quick whitespace fix
---
packages/app/src/debug/DebugFailedTest.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/app/src/debug/DebugFailedTest.vue b/packages/app/src/debug/DebugFailedTest.vue
index 4ebc2f2d5705..be169e7ac389 100644
--- a/packages/app/src/debug/DebugFailedTest.vue
+++ b/packages/app/src/debug/DebugFailedTest.vue
@@ -28,7 +28,7 @@
:class="type === 'ELLIPSIS' ? 'px-2.5 shrink-0 lg:hidden' :
type === 'MIDDLE' ? 'truncate px-2.5 hidden lg:block' :
type === 'LAST-PART-END' ? 'shrink-0 whitespace-pre' :
- type === 'LAST-PART-START' ? 'pl-2.5 truncate' : 'px-2.5 truncate'"
+ type === 'LAST-PART-START' ? 'pl-2.5 truncate whitespace-pre' : 'px-2.5 truncate'"
>
From 2b1fd83f0cb3d7de0d47e82edd9639b3902d525e Mon Sep 17 00:00:00 2001
From: Stokes Player
Date: Wed, 18 Jan 2023 07:52:41 -0500
Subject: [PATCH 19/40] Building windows and binaries
---
.circleci/workflows.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml
index 060775ed89c6..0af44dfcb422 100644
--- a/.circleci/workflows.yml
+++ b/.circleci/workflows.yml
@@ -28,7 +28,7 @@ mainBuildFilters: &mainBuildFilters
only:
- develop
- /^release\/\d+\.\d+\.\d+$/
- - 'macOS-launch-arm-browser'
+ - 'feature/IATR-M0'
# 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
@@ -37,7 +37,7 @@ macWorkflowFilters: &darwin-workflow-filters
when:
or:
- equal: [ develop, << pipeline.git.branch >> ]
- - equal: [ 'macOS-launch-arm-browser', << pipeline.git.branch >> ]
+ - equal: [ 'feature/IATR-M0', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -45,7 +45,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
when:
or:
- equal: [ develop, << pipeline.git.branch >> ]
- - equal: [ 'macOS-launch-arm-browser', << pipeline.git.branch >> ]
+ - equal: [ 'feature/IATR-M0', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
@@ -129,7 +129,7 @@ commands:
- run:
name: Check current branch to persist artifacts
command: |
- if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "macOS-launch-arm-browser" ]]; then
+ if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "feature/IATR-M0" ]]; then
echo "Not uploading artifacts or posting install comment for this branch."
circleci-agent step halt
fi
From 1a35da7e07bdf35c94ca2e8e22cdf3f9d044f4a0 Mon Sep 17 00:00:00 2001
From: Stokes Player
Date: Wed, 18 Jan 2023 07:54:20 -0500
Subject: [PATCH 20/40] Addinging windows
---
.circleci/workflows.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml
index 0af44dfcb422..e606daccc65f 100644
--- a/.circleci/workflows.yml
+++ b/.circleci/workflows.yml
@@ -63,7 +63,7 @@ windowsWorkflowFilters: &windows-workflow-filters
when:
or:
- equal: [ develop, << pipeline.git.branch >> ]
- - equal: [ 'retry-flake', << pipeline.git.branch >> ]
+ - equal: [ 'feature/IATR-M0', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
From 1a31dd59ef5b8189fcc585050d2a85d36c918e9b Mon Sep 17 00:00:00 2001
From: Stokes Player
Date: Wed, 18 Jan 2023 11:43:28 -0500
Subject: [PATCH 21/40] Fix for windows paths for debug filter
---
packages/app/src/runner/unifiedRunner.ts | 5 +++--
packages/graphql/schemas/schema.graphql | 2 +-
packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/packages/app/src/runner/unifiedRunner.ts b/packages/app/src/runner/unifiedRunner.ts
index 5ac68beadec3..95869cbf4e6e 100644
--- a/packages/app/src/runner/unifiedRunner.ts
+++ b/packages/app/src/runner/unifiedRunner.ts
@@ -4,7 +4,7 @@ import { useSpecStore } from '../store'
import { useSelectorPlaygroundStore } from '../store/selector-playground-store'
import { RUN_ALL_SPECS, RUN_ALL_SPECS_KEY, SpecFile } from '@packages/types/src'
import { LocationQuery, useRoute } from 'vue-router'
-import { getPathForPlatform } from '../paths'
+import { getPathForPlatform, posixify } from '../paths'
import { isEqual } from 'lodash'
import { gql, useMutation } from '@urql/vue'
import { TestsForRunDocument } from '../generated/graphql'
@@ -62,7 +62,8 @@ export function useUnifiedRunner () {
}
if (route.query.mode && route.query.mode === 'debug') {
- const res = await testsForRunMutation.executeMutation({ spec: activeSpecInSpecsList.relative })
+ const posixPath = posixify(activeSpecInSpecsList.relative)
+ const res = await testsForRunMutation.executeMutation({ spec: posixPath })
specStore.setTestFilter(res.data?.testsForRun?.length ? res.data.testsForRun : undefined)
} else {
diff --git a/packages/graphql/schemas/schema.graphql b/packages/graphql/schemas/schema.graphql
index 9d91b87895cd..fdceaa54ca9d 100644
--- a/packages/graphql/schemas/schema.graphql
+++ b/packages/graphql/schemas/schema.graphql
@@ -1727,7 +1727,7 @@ type Mutation {
"""Return the set of test titles for the given spec path"""
testsForRun(
- """Spec path relative to the project"""
+ """Spec path relative to the project in posix format"""
spec: String!
): [String!]
diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
index 9d2a07a38b70..a4d1ce0612d2 100644
--- a/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
+++ b/packages/graphql/src/schemaTypes/objectTypes/gql-Mutation.ts
@@ -780,7 +780,7 @@ export const mutation = mutationType({
description: 'Return the set of test titles for the given spec path',
args: {
spec: nonNull(stringArg({
- description: 'Spec path relative to the project',
+ description: 'Spec path relative to the project in posix format',
})),
},
resolve: (source, args, ctx) => {
From be5e5348953c1549412ba476efea70b95f6084f3 Mon Sep 17 00:00:00 2001
From: Stokes Player
Date: Thu, 19 Jan 2023 10:27:31 -0500
Subject: [PATCH 22/40] fix: update query names for better logging (#25514)
---
.../src/sources/RelevantRunSpecsDataSource.ts | 46 +++++++++++--------
.../src/sources/RelevantRunsDataSource.ts | 2 +-
2 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/packages/data-context/src/sources/RelevantRunSpecsDataSource.ts b/packages/data-context/src/sources/RelevantRunSpecsDataSource.ts
index dd04253b4ea8..ea38d1f3760b 100644
--- a/packages/data-context/src/sources/RelevantRunSpecsDataSource.ts
+++ b/packages/data-context/src/sources/RelevantRunSpecsDataSource.ts
@@ -11,7 +11,18 @@ import type { CloudRunStatus } from '@packages/graphql/src/gen/cloud-source-type
const debug = debugLib('cypress:data-context:sources:RelevantRunSpecsDataSource')
const RELEVANT_RUN_SPEC_OPERATION_DOC = gql`
- query RelevantRunsDataSource_latestRunUpdateSpecData(
+ fragment RelevantRunSpecsDataSource_Runs on CloudRun {
+ id
+ runNumber
+ status
+ specs {
+ id
+ status
+ groupIds
+ }
+ }
+
+ query RelevantRunSpecsDataSource_Specs(
$projectSlug: String!
$currentRunNumber: Int!
$hasCurrent: Boolean!
@@ -24,21 +35,11 @@ const RELEVANT_RUN_SPEC_OPERATION_DOC = gql`
id
current: runByNumber(runNumber: $currentRunNumber) @include(if: $hasCurrent) {
id
- runNumber
- status
- specs {
- id
- status
- }
+ ...RelevantRunSpecsDataSource_Runs
}
next: runByNumber(runNumber: $nextRunNumber) @include(if: $hasNext) {
id
- runNumber
- status
- specs {
- id
- status
- }
+ ...RelevantRunSpecsDataSource_Runs
}
}
}
@@ -56,7 +57,7 @@ export const SPECS_EMPTY_RETURN: RunSpecReturn = {
const INCOMPLETE_STATUSES: CloudSpecStatus[] = ['RUNNING', 'UNCLAIMED']
-type RunSpecReturn = {
+export type RunSpecReturn = {
runSpecs: CurrentProjectRelevantRunSpecs
statuses: {
current?: CloudRunStatus
@@ -64,6 +65,9 @@ type RunSpecReturn = {
}
}
+//Not ideal typing for this return since the query is not fetching all the fields, but better than nothing
+export type RelevantRunSpecsCloudResult = { cloudProjectBySlug: { __typename?: string, current?: Partial, next?: Partial } } & Pick
+
/**
* DataSource to encapsulate querying Cypress Cloud for runs that match a list of local Git commit shas
*/
@@ -83,9 +87,14 @@ export class RelevantRunSpecsDataSource {
}
#calculateSpecMetadata (specs: CloudSpecRun[]) {
+ //mimic logic in Cloud to sum up the count of groups per spec to give the total spec counts
+ const countGroupsForSpec = (specs: CloudSpecRun[]) => {
+ return specs.map((spec) => spec.groupIds?.length || 0).reduce((acc, curr) => acc += curr, 0)
+ }
+
return {
- totalSpecs: specs.length,
- completedSpecs: specs.map((spec) => spec.status || 'UNCLAIMED').filter((status) => !INCOMPLETE_STATUSES.includes(status)).length,
+ totalSpecs: countGroupsForSpec(specs),
+ completedSpecs: countGroupsForSpec(specs.filter((spec) => !INCOMPLETE_STATUSES.includes(spec.status || 'UNCLAIMED'))),
}
}
@@ -106,10 +115,7 @@ export class RelevantRunSpecsDataSource {
debug(`Fetching specs for ${projectSlug} and %o`, runs)
- //Not ideal typing for this return since the query is not fetching all the fields, but better than nothing
- type CloudResult = { cloudProjectBySlug: { __typename: string, current?: CloudRun, next?: CloudRun } } & Pick
-
- const result = await this.ctx.cloud.executeRemoteGraphQL({
+ const result = await this.ctx.cloud.executeRemoteGraphQL({
fieldName: 'cloudProjectBySlug',
operationDoc: RELEVANT_RUN_SPEC_OPERATION_DOC,
operation: RELEVANT_RUN_SPEC_UPDATE_OPERATION,
diff --git a/packages/data-context/src/sources/RelevantRunsDataSource.ts b/packages/data-context/src/sources/RelevantRunsDataSource.ts
index edd7504235b9..6c2277869027 100644
--- a/packages/data-context/src/sources/RelevantRunsDataSource.ts
+++ b/packages/data-context/src/sources/RelevantRunsDataSource.ts
@@ -10,7 +10,7 @@ import { Poller } from '../polling'
const debug = debugLib('cypress:data-context:sources:RelevantRunsDataSource')
const RELEVANT_RUN_OPERATION_DOC = gql`
- query RelevantRunsDataSource_latestRunUpdateSpecData(
+ query RelevantRunsDataSource_RunsByCommitShas(
$projectSlug: String!
$shas: [String!]!
) {
From 771debb72a701164a38883f1b41212ec26957674 Mon Sep 17 00:00:00 2001
From: Mark Noonan
Date: Wed, 25 Jan 2023 11:37:43 -0500
Subject: [PATCH 23/40] chore: ui tweaks (#25555)
Co-authored-by: Stokes Player
---
.../app/src/debug/DebugNewRelevantRunBar.vue | 4 ++--
packages/app/src/debug/DebugPageHeader.cy.tsx | 21 +++++++++++++++++++
packages/app/src/debug/DebugPageHeader.vue | 19 +++++++++--------
packages/app/src/debug/DebugSpec.vue | 6 +++---
.../app/src/debug/DebugSpecLimitBanner.vue | 4 ++--
.../src/debug/GroupedDebugFailedTest.cy.tsx | 5 +++++
packages/app/src/debug/StatsMetadata.vue | 2 +-
7 files changed, 44 insertions(+), 17 deletions(-)
diff --git a/packages/app/src/debug/DebugNewRelevantRunBar.vue b/packages/app/src/debug/DebugNewRelevantRunBar.vue
index 99f4b622cffe..f0d8ef11e4fd 100644
--- a/packages/app/src/debug/DebugNewRelevantRunBar.vue
+++ b/packages/app/src/debug/DebugNewRelevantRunBar.vue
@@ -2,11 +2,11 @@
', {
.should('have.text', 'You are 1 commit ahead')
})
+ it('renders long commit message', () => {
+ const longText = 'This commit contains many changes which are described at great length in this commit summary, arguably the length is long enough to be considered unwieldy, but nevertheless we should render the text nicely'
+
+ cy.mountFragment(DebugPageHeaderFragmentDoc, {
+ render: (gqlVal) => {
+ if (!gqlVal.commitInfo?.summary) {
+ throw new Error('Missing commit info for test')
+ }
+
+ gqlVal.commitInfo.summary = longText
+
+ return (
+
+ )
+ },
+ })
+
+ cy.contains(longText).should('be.visible')
+ cy.percySnapshot()
+ })
+
it('renders no commit message', () => {
cy.mountFragment(DebugPageHeaderFragmentDoc, {
render: (gqlVal) => {
diff --git a/packages/app/src/debug/DebugPageHeader.vue b/packages/app/src/debug/DebugPageHeader.vue
index c10ddcc0dccd..498f4e011044 100644
--- a/packages/app/src/debug/DebugPageHeader.vue
+++ b/packages/app/src/debug/DebugPageHeader.vue
@@ -9,37 +9,38 @@
>