From 41bbb55ded84829668782f4fe76637d3acc9b6bd Mon Sep 17 00:00:00 2001 From: astone123 Date: Tue, 21 Feb 2023 10:13:51 -0700 Subject: [PATCH 1/2] chore: add guide for app cloud testing --- guides/app-cloud-testing.md | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 guides/app-cloud-testing.md diff --git a/guides/app-cloud-testing.md b/guides/app-cloud-testing.md new file mode 100644 index 000000000000..c19a0ba497d7 --- /dev/null +++ b/guides/app-cloud-testing.md @@ -0,0 +1,57 @@ +# App <--> Cloud Testing + +Testing communication between the Cypress App and Cypress Cloud can be complex depending on how much data is going back and forth. For example, we recently completed the Debug page feature which involved writing some e2e tests to verify that the page was functioning correctly with the expected data from Cypress Cloud. In this document, we'll share some of our findings from the process of writing these tests for the Debug page. + +## Working with GraphQL requests + +We use GraphQL to interface with Cypress Cloud, so there are some things to know when writing e2e tests between the App and Cloud. + +### GraphQL requests over fetch + +By default, GraphQL queries use web sockets to fetch data. This doesn't let us intercept these messages and return a mock response in the ideal way (using cy.intercept) to get our app into the desired state for the test. We can set the GraphQL client to use fetch rather than WS by adding this hook at the top of our spec file. + +You can see an example of this in [our spec for the Debug page](/packages/app/cypress/e2e/debug.cy.ts#L4). + +```js +Cypress.on('window:before:load', (win) => { + win.__CYPRESS_GQL_NO_SOCKET__ = 'true' +}) +``` + +Note that this does not affect [GraphQL subscriptions](#intercepting-graphql-subscriptions). + +Now that the GraphQL requests to Cypress Cloud are happening over fetch, we can use `cy.intercept` to intercept the requests and do whatever we need to do (in most cases, return a JSON fixture as a response to the request). + +### Creating JSON fixtures from GraphQL requests + +Another benefit of making our GraphQL requests over fetch is that we can easily see the real responses from Cypress Cloud in the Network tab of our browser developer tools. This is especially useful when we have large responses coming back from Cypress Cloud that we want to mock in our tests. + +We can start our fixture by copying the real response from the dev tools response into our fixture and then modifying individual fields to tweak our app state. Then we can intercept the GraphQL request and return our fixture. + +You can see an example of this in [our spec for the Debug page](/packages/app/cypress/e2e/debug.cy.ts#L35). + +```js +cy.intercept('query-Debug', { + fixture: 'debug-Passing/gql-Debug.json', +}) +``` + +### Intercepting GraphQL subscriptions + +Subscriptions always use web sockets, so in order to intercept these we need to do something different. For subscriptions, we need to use `cy.remoteGraphQLIntercept` to check if the operation is related to our subscription and if it is, return our fixture instead. + +You can see an example of this in [our spec for the Debug page](/packages/app/cypress/e2e/debug.cy.ts#L23). + +```js +import RelevantRunsDataSource_RunsByCommitShas from '../fixtures/gql-RelevantRunsDataSource_RunsByCommitShas.json' + +beforeEach(() => { + cy.remoteGraphQLIntercept((obj, _testState, options) => { + if (obj.operationName === 'RelevantRunsDataSource_RunsByCommitShas') { + obj.result.data = options.RelevantRunsDataSource_RunsByCommitShas.data + } + + return obj.result + }, { RelevantRunsDataSource_RunsByCommitShas }) +}) +``` \ No newline at end of file From 6a201d697994103c8c6ef00bfdee58455f8bc24f Mon Sep 17 00:00:00 2001 From: astone123 Date: Tue, 21 Feb 2023 19:03:49 -0700 Subject: [PATCH 2/2] clarifications --- guides/app-cloud-testing.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/guides/app-cloud-testing.md b/guides/app-cloud-testing.md index c19a0ba497d7..dba4043fd4d5 100644 --- a/guides/app-cloud-testing.md +++ b/guides/app-cloud-testing.md @@ -8,7 +8,7 @@ We use GraphQL to interface with Cypress Cloud, so there are some things to know ### GraphQL requests over fetch -By default, GraphQL queries use web sockets to fetch data. This doesn't let us intercept these messages and return a mock response in the ideal way (using cy.intercept) to get our app into the desired state for the test. We can set the GraphQL client to use fetch rather than WS by adding this hook at the top of our spec file. +By default, GraphQL queries use web sockets to fetch data. This doesn't let us intercept these messages and return a mock response using `cy.intercept` to get our app into the desired state for the test. We can set the GraphQL client to use fetch rather than WS by adding this hook at the top of our spec file. You can see an example of this in [our spec for the Debug page](/packages/app/cypress/e2e/debug.cy.ts#L4). @@ -18,10 +18,10 @@ Cypress.on('window:before:load', (win) => { }) ``` -Note that this does not affect [GraphQL subscriptions](#intercepting-graphql-subscriptions). - Now that the GraphQL requests to Cypress Cloud are happening over fetch, we can use `cy.intercept` to intercept the requests and do whatever we need to do (in most cases, return a JSON fixture as a response to the request). +Note that this intercepts requests between the App and Server. This means that any logic that we have in the `data-context` layer for this query will not be executed by the test because the query will be intercepted before it runs. + ### Creating JSON fixtures from GraphQL requests Another benefit of making our GraphQL requests over fetch is that we can easily see the real responses from Cypress Cloud in the Network tab of our browser developer tools. This is especially useful when we have large responses coming back from Cypress Cloud that we want to mock in our tests. @@ -36,9 +36,15 @@ cy.intercept('query-Debug', { }) ``` -### Intercepting GraphQL subscriptions +### Intercepting subscriptions and requests from the server + +There are a few situations in which we need to use `cy.remoteGraphQLIntercept` to intercept a request: + +- If the request originates from the server +- If the request is a subscription (these will always be over web sockets, so cy.intercept doesn't work) +- If there is server-side logic in the resolver that we want to cover with our test -Subscriptions always use web sockets, so in order to intercept these we need to do something different. For subscriptions, we need to use `cy.remoteGraphQLIntercept` to check if the operation is related to our subscription and if it is, return our fixture instead. +`cy.remoteGraphQLIntercept` intercepts the request at the server level, so we are able to return fixture data here and have the resolver continue on as if this is the data that was returned from Cypress Cloud. You can see an example of this in [our spec for the Debug page](/packages/app/cypress/e2e/debug.cy.ts#L23).