Skip to content

Commit

Permalink
fix: Launchpad perpetual loading state, in certain circumstances (#29597
Browse files Browse the repository at this point in the history
)

* fix: refetch current project on geometric delay in Main.vue if config has not yet loaded

* adds test for config file load behavior in Main.vue

* changelog

* fix extraneous refetches when config is in error state

* Update packages/launchpad/src/Main.vue

Co-authored-by: Ryan Manuel <ryanm@cypress.io>

* Update packages/launchpad/src/Main.vue

Co-authored-by: Bill Glesias <bglesias@gmail.com>

* Update cli/CHANGELOG.md

Co-authored-by: Bill Glesias <bglesias@gmail.com>

* Update packages/launchpad/cypress/e2e/project-setup.cy.ts

Co-authored-by: Bill Glesias <bglesias@gmail.com>

* Update packages/launchpad/cypress/e2e/project-setup.cy.ts

Co-authored-by: Bill Glesias <bglesias@gmail.com>

---------

Co-authored-by: Ryan Manuel <ryanm@cypress.io>
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
Co-authored-by: Bill Glesias <bglesias@gmail.com>
  • Loading branch information
4 people committed Jun 3, 2024
1 parent f2894c4 commit 687eb60
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 1 deletion.
1 change: 1 addition & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ _Released 6/4/2024 (PENDING)_

**Bugfixes:**

- Fixed a situation where the Launchpad would hang if the project config had not been loaded when the Launchpad first queries the current project. Fixes [#29486](https://github.com/cypress-io/cypress/issues/29486).
- Pre-emptively fix behavior with Chrome for when `unload` events are forcefully deprecated by using `pagehide` as a proxy. Fixes [#29241](https://github.com/cypress-io/cypress/issues/29241).

## 13.10.0
Expand Down
52 changes: 52 additions & 0 deletions packages/launchpad/cypress/e2e/project-setup.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,4 +694,56 @@ describe('Launchpad: Setup Project', () => {
cy.contains('h1', 'Project setup')
})
})

describe('config loading state', () => {
describe('when currentProject config loading state changes from loading to loaded after the first query', () => {
beforeEach(() => {
let responseCount = 0

cy.intercept('POST', '/__launchpad/graphql/query-MainLaunchpadQuery', (req) => {
req.reply((res) => {
responseCount++
if (responseCount === 2) {
res.body.data.currentProject.isLoadingConfigFile = false
} else if (responseCount === 1) {
res.body.data.currentProject.isLoadingConfigFile = true
} else {
throw new Error('Too many calls to MainLaunchpadQuery')
}
})
})
})

it('eventually displays the launchpad', () => {
scaffoldAndOpenProject('pristine')
cy.visitLaunchpad()
})
})

describe('when the initial config is loading, but eventually fails', () => {
it('shows the error message, and only calls the endpoint enough times to receive the baseError', () => {
let callCount = 0
let resWithBaseError: number | undefined

cy.intercept('POST', '/__launchpad/graphql/query-MainLaunchpadQuery', (req) => {
if (resWithBaseError && callCount >= resWithBaseError) {
throw new Error('Too many calls to MainLaunchpadQuery')
}

callCount++
req.reply((res) => {
res.body.data.currentProject.isLoadingConfigFile = true
if (res.body.data.baseError) {
resWithBaseError = callCount
}
})
})

scaffoldAndOpenProject('config-with-ts-syntax-error')
cy.visitLaunchpad()
cy.get('[data-cy=error-header]').contains('Cypress configuration error')
cy.wait(1000)
})
})
})
})
52 changes: 51 additions & 1 deletion packages/launchpad/src/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ import MigrationWizard from './migration/MigrationWizard.vue'
import ScaffoldedFiles from './setup/ScaffoldedFiles.vue'
import MajorVersionWelcome from './migration/MajorVersionWelcome.vue'
import { useI18n } from '@cy/i18n'
import { computed, ref } from 'vue'
import { computed, ref, watch } from 'vue'
import LaunchpadHeader from './setup/LaunchpadHeader.vue'
import OpenBrowser from './setup/OpenBrowser.vue'
import LoginConnectModals from '@cy/gql-components/LoginConnectModals.vue'
Expand Down Expand Up @@ -193,6 +193,56 @@ const resetErrorAndLoadConfig = (id: string) => {
}
const query = useQuery({ query: MainLaunchpadQueryDocument })
const currentProject = computed(() => query.data.value?.currentProject)
const hasBaseError = computed(() => !!query.data.value?.baseError)
const refetchDelaying = ref(false)
const refetchCount = ref(0)
/*
* Sometimes the config file has not been loaded by the DataContext's config manager by the
* time the MainLaunchpadQueryDocument request is sent off. The server ends up resolving
* the isLoadingConfigFile field as false. In certain situations, there can be a race between
* opening the project and the DataContext completing its retrieval of the configuration.
* In these cases, we want to retry the query until the config file is fully loaded.
*
* If the ProjectConfigIPC encounters an error while loading the config, it will update the
* baseError field via subscription, so there is not a limit set here on retries.
*/
watch(
[currentProject, query.fetching],
([currentProject, isFetchingProject]) => {
const isLoadingConfig = currentProject?.isLoadingConfigFile
/*
* conditions for refetch are:
* - There is a current project, but Config file has not yet loaded
* - There are no pending (delayed) refetches, or fetches in progress
* - There is no baseError - we don't want to continue to refetch if
* things have errored out.
*/
if (
currentProject &&
isLoadingConfig &&
!isFetchingProject &&
!refetchDelaying.value &&
!hasBaseError.value
) {
refetchDelaying.value = true
refetchCount.value++
setTimeout(() => {
refetchDelaying.value = false
if (
(currentProject && !isLoadingConfig) || hasBaseError.value
) {
return
}
query.executeQuery({ requestPolicy: 'network-only' })
}, (refetchCount.value + 1) * 500)
}
},
)
function handleClearLandingPage () {
setMajorVersionWelcomeDismissed(MAJOR_VERSION_FOR_CONTENT)
Expand Down

4 comments on commit 687eb60

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 687eb60 Jun 3, 2024

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/13.11.0/linux-arm64/develop-687eb6029f4a0cb22d411b12b3fd16df973c4da0/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 687eb60 Jun 3, 2024

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/13.11.0/win32-x64/develop-687eb6029f4a0cb22d411b12b3fd16df973c4da0/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 687eb60 Jun 3, 2024

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/13.11.0/darwin-arm64/develop-687eb6029f4a0cb22d411b12b3fd16df973c4da0/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 687eb60 Jun 3, 2024

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/13.11.0/darwin-x64/develop-687eb6029f4a0cb22d411b12b3fd16df973c4da0/cypress.tgz

Please sign in to comment.