diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index fc6441362e3f..3f25f57b5df5 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -3,6 +3,10 @@ _Released 05/23/2023 (PENDING)_ +**Features:** + +- Add Git-related messages for the [Runs page](https://docs.cypress.io/guides/core-concepts/cypress-app#Runs) and [Debug page](https://docs.cypress.io/guides/cloud/runs#Debug) when users aren't using Git or there are no recorded runs for the current branch. Fixes [#26680](https://github.com/cypress-io/cypress/issues/26680). + **Bugfixes:** - Reverted [#26452](https://github.com/cypress-io/cypress/pull/26630) which introduced a bug that prevents users from using End to End with Yarn 3. Fixed in [#26735](https://github.com/cypress-io/cypress/pull/26735). Fixes [#26676](https://github.com/cypress-io/cypress/issues/26676). diff --git a/packages/app/cypress/e2e/runs.cy.ts b/packages/app/cypress/e2e/runs.cy.ts index cdf45b776561..e2d7e74fd136 100644 --- a/packages/app/cypress/e2e/runs.cy.ts +++ b/packages/app/cypress/e2e/runs.cy.ts @@ -2,6 +2,10 @@ import defaultMessages from '@packages/frontend-shared/src/locales/en-US.json' import type { SinonStub } from 'sinon' function moveToRunsPage (): void { + cy.withCtx((ctx, o) => { + o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch') + }) + cy.findByTestId('sidebar-link-runs-page').click() cy.findByTestId('app-header-bar').findByText('Runs').should('be.visible') cy.findByTestId('runs-container').should('be.visible') @@ -34,6 +38,9 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.scaffoldProject('component-tests') cy.openProject('component-tests') cy.startAppServer('component') + cy.withCtx((ctx, o) => { + o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch') + }) }) it('resolves the runs page', () => { @@ -99,7 +106,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { moveToRunsPage() cy.contains('a', 'OVERLIMIT').click() - cy.withCtx((ctx) => { + cy.withCtx((ctx, o) => { expect((ctx.actions.electron.openExternal as SinonStub).lastCall.lastArg).to.contain('http://dummy.cypress.io/runs/4') }) }) @@ -315,6 +322,7 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { cy.withCtx(async (ctx, o) => { o.sinon.spy(ctx.cloud, 'executeRemoteGraphQL') + o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch') const config = await ctx.project.getConfig() expect(config.projectId).to.not.equal('newProjectId') @@ -757,6 +765,10 @@ describe('App: Runs', { viewportWidth: 1200 }, () => { }) it('should remove the alert warning if the app reconnects to the internet', () => { + cy.withCtx((ctx, o) => { + o.sinon.stub(ctx.lifecycleManager.git!, 'currentBranch').value('fakeBranch') + }) + cy.loginUser() cy.visitApp() cy.wait(1000) diff --git a/packages/app/package.json b/packages/app/package.json index b0a4cff12435..109d59767634 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -21,7 +21,7 @@ "dependencies": {}, "devDependencies": { "@cypress-design/vue-button": "0.9.2", - "@cypress-design/vue-icon": "0.22.1", + "@cypress-design/vue-icon": "0.22.2", "@cypress-design/vue-statusicon": "0.4.3", "@graphql-typed-document-node/core": "^3.1.0", "@headlessui/vue": "1.4.0", diff --git a/packages/app/src/debug/DebugContainer.cy.tsx b/packages/app/src/debug/DebugContainer.cy.tsx index 9b8f30362d8c..d19613cde2f8 100644 --- a/packages/app/src/debug/DebugContainer.cy.tsx +++ b/packages/app/src/debug/DebugContainer.cy.tsx @@ -46,6 +46,7 @@ describe('', () => { const userProjectStatusStore = useUserProjectStatusStore() userProjectStatusStore.setHasInitiallyLoaded() + userProjectStatusStore.setProjectFlag('isUsingGit', true) validateEmptyState([defaultMessages.debugPage.emptyStates.connectToCypressCloud, defaultMessages.debugPage.emptyStates.connect.title, defaultMessages.debugPage.emptyStates.connect.description]) cy.findByRole('button', { name: 'Connect to Cypress Cloud' }).should('be.visible') @@ -56,6 +57,7 @@ describe('', () => { userProjectStatusStore.setUserFlag('isLoggedIn', true) userProjectStatusStore.setProjectFlag('isProjectConnected', false) + userProjectStatusStore.setProjectFlag('isUsingGit', true) userProjectStatusStore.setHasInitiallyLoaded() validateEmptyState([defaultMessages.debugPage.emptyStates.connect.title, defaultMessages.debugPage.emptyStates.connect.description]) @@ -67,6 +69,7 @@ describe('', () => { userProjectStatusStore.setUserFlag('isLoggedIn', true) userProjectStatusStore.setProjectFlag('isProjectConnected', true) + userProjectStatusStore.setProjectFlag('isUsingGit', true) userProjectStatusStore.setHasInitiallyLoaded() cy.mountFragment(DebugSpecsFragmentDoc, { variableTypes: DebugSpecVariableTypes, @@ -78,20 +81,43 @@ describe('', () => { cy.findByDisplayValue('npx cypress run --record --key 2aaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa').should('be.visible') }) - it('errors', () => { + it('is not using git', () => { const userProjectStatusStore = useUserProjectStatusStore() userProjectStatusStore.setUserFlag('isLoggedIn', true) userProjectStatusStore.setProjectFlag('isProjectConnected', true) + userProjectStatusStore.setProjectFlag('isUsingGit', false) userProjectStatusStore.setHasInitiallyLoaded() cy.mountFragment(DebugSpecsFragmentDoc, { variableTypes: DebugSpecVariableTypes, variables: defaultVariables, - render: (gqlVal) => , + render: (gqlVal) => , + }) + + cy.findByTestId('debug-empty-title').should('contain.text', 'Git repository not detected') + }) + + it('has no runs for the current branch', () => { + const { setUserFlag, setProjectFlag, cloudStatusMatches, setHasInitiallyLoaded } = useUserProjectStatusStore() + + setUserFlag('isLoggedIn', true) + setUserFlag('isMemberOfOrganization', true) + setProjectFlag('isProjectConnected', true) + setProjectFlag('hasNoRecordedRuns', true) + setProjectFlag('hasNonExampleSpec', true) + setProjectFlag('isConfigLoaded', true) + setProjectFlag('isUsingGit', true) + setHasInitiallyLoaded() + + cy.mountFragment(DebugSpecsFragmentDoc, { + variableTypes: DebugSpecVariableTypes, + variables: defaultVariables, + render: (gqlVal) => , }) - cy.findByTestId('debug-empty').should('not.exist') - cy.findByTestId('debug-alert').should('be.visible') + expect(cloudStatusMatches('needsRecordedRun')).equals(true) + + cy.contains('No runs found for your branch') }) }) @@ -101,6 +127,7 @@ describe('', () => { userProjectStatusStore.setUserFlag('isLoggedIn', true) userProjectStatusStore.setProjectFlag('isProjectConnected', true) + userProjectStatusStore.setProjectFlag('isUsingGit', true) userProjectStatusStore.setHasInitiallyLoaded() }) @@ -228,6 +255,7 @@ describe('', () => { userProjectStatusStore.setUserFlag('isLoggedIn', true) userProjectStatusStore.setProjectFlag('isProjectConnected', true) + userProjectStatusStore.setProjectFlag('isUsingGit', true) userProjectStatusStore.setHasInitiallyLoaded() }) diff --git a/packages/app/src/debug/DebugContainer.vue b/packages/app/src/debug/DebugContainer.vue index 94072128c7a7..7c82b4ce64c4 100644 --- a/packages/app/src/debug/DebugContainer.vue +++ b/packages/app/src/debug/DebugContainer.vue @@ -5,9 +5,7 @@ {{ t('launchpadErrors.noInternet.connectProject') }} - + + + { return props.gql?.currentProject?.cloudProject?.__typename === 'CloudProject' ? props.gql.currentProject.cloudProject diff --git a/packages/app/src/debug/empty/DebugBranchError.cy.tsx b/packages/app/src/debug/empty/DebugBranchError.cy.tsx new file mode 100644 index 000000000000..6d259613435e --- /dev/null +++ b/packages/app/src/debug/empty/DebugBranchError.cy.tsx @@ -0,0 +1,12 @@ +import DebugBranchError from './DebugBranchError.vue' +import { defaultMessages } from '@cy/i18n' + +describe('', () => { + it('can mount', () => { + cy.mount() + cy.get('[data-cy=debug-empty-title]').should('contain.text', defaultMessages.debugPage.emptyStates.noRunsFoundForBranch) + cy.get('[data-cy=debug-empty-description]').should('contain.text', defaultMessages.debugPage.emptyStates.noRunsForBranchMessage) + // The utm_source will be Binary%3A+App in production`open` mode but we assert using Binary%3A+Launchpad as this is the value in CI + cy.contains(defaultMessages.links.learnMoreButton).should('have.attr', 'href', 'https://on.cypress.io/git-info?utm_source=Binary%3A+Launchpad&utm_medium=Debug+Tab&utm_campaign=No+Runs+Found') + }) +}) diff --git a/packages/app/src/debug/empty/DebugBranchError.vue b/packages/app/src/debug/empty/DebugBranchError.vue new file mode 100644 index 000000000000..21c04340e785 --- /dev/null +++ b/packages/app/src/debug/empty/DebugBranchError.vue @@ -0,0 +1,22 @@ + + + diff --git a/packages/app/src/debug/empty/DebugEmptyStates.cy.tsx b/packages/app/src/debug/empty/DebugEmptyStates.cy.tsx index 20f1acb8a0c2..25508bd93095 100644 --- a/packages/app/src/debug/empty/DebugEmptyStates.cy.tsx +++ b/packages/app/src/debug/empty/DebugEmptyStates.cy.tsx @@ -119,12 +119,10 @@ describe('Debug page empty states', { defaultCommandTimeout: 250 }, () => { }) }) - context('error', () => { + context('not using git', () => { it('renders', () => { mountWithGql() - - cy.findByRole('link', { name: 'Learn more about debugging CI failures in Cypress' }).should('have.attr', 'href', 'https://on.cypress.io/debug-page?utm_source=Binary%3A+Launchpad&utm_medium=Debug+Tab&utm_campaign=Learn+More') - + cy.findByText('Git repository not detected').should('be.visible') cy.percySnapshot() }) }) diff --git a/packages/app/src/debug/empty/DebugEmptyView.vue b/packages/app/src/debug/empty/DebugEmptyView.vue index db4624830c27..324e992fdd17 100644 --- a/packages/app/src/debug/empty/DebugEmptyView.vue +++ b/packages/app/src/debug/empty/DebugEmptyView.vue @@ -1,12 +1,25 @@