-
-
Notifications
You must be signed in to change notification settings - Fork 511
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(graphql): add test on anonymous operation warning (#1693)
- Loading branch information
1 parent
6239a0f
commit bb02e57
Showing
5 changed files
with
344 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { graphql, HttpResponse } from 'msw' | ||
import { setupWorker } from 'msw/browser' | ||
|
||
const worker = setupWorker() | ||
worker.start() | ||
|
||
// @ts-ignore | ||
window.msw = { | ||
worker, | ||
graphql, | ||
HttpResponse, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
import { HttpServer } from '@open-draft/test-server/http' | ||
import { test, expect } from '../playwright.extend' | ||
import { gql } from '../../support/graphql' | ||
import { waitFor } from '../../support/waitFor' | ||
|
||
declare namespace window { | ||
export const msw: { | ||
worker: import('msw/browser').SetupWorkerApi | ||
graphql: typeof import('msw').graphql | ||
HttpResponse: typeof import('msw').HttpResponse | ||
} | ||
} | ||
|
||
const httpServer = new HttpServer((app) => { | ||
app.post('/graphql', (req, res) => { | ||
res.json({ | ||
data: { | ||
user: { | ||
id: 'abc-123', | ||
}, | ||
}, | ||
}) | ||
}) | ||
}) | ||
|
||
test.beforeAll(async () => { | ||
await httpServer.listen() | ||
}) | ||
|
||
test.afterAll(async () => { | ||
await httpServer.close() | ||
}) | ||
|
||
test('does not warn on anonymous GraphQL operation when no GraphQL handlers are present', async ({ | ||
loadExample, | ||
query, | ||
spyOnConsole, | ||
}) => { | ||
await loadExample(require.resolve('./anonymous-operation.mocks.ts')) | ||
const consoleSpy = spyOnConsole() | ||
|
||
const endpointUrl = httpServer.http.url('/graphql') | ||
const response = await query(endpointUrl, { | ||
query: gql` | ||
# Intentionally anonymous query. | ||
query { | ||
user { | ||
id | ||
} | ||
} | ||
`, | ||
}) | ||
|
||
const json = await response.json() | ||
|
||
// Must get the original server response. | ||
expect(json).toEqual({ | ||
data: { | ||
user: { | ||
id: 'abc-123', | ||
}, | ||
}, | ||
}) | ||
|
||
await waitFor(() => { | ||
// Must print a generic unhandled GraphQL request warning. | ||
// This has nothing to do with the operation being anonymous. | ||
expect(consoleSpy.get('warning')).toEqual([ | ||
`\ | ||
[MSW] Warning: captured a request without a matching request handler: | ||
• anonymous query (POST ${endpointUrl}) | ||
If you still wish to intercept this unhandled request, please create a request handler for it. | ||
Read more: https://mswjs.io/docs/getting-started/mocks`, | ||
]) | ||
}) | ||
|
||
// // Must print the warning because anonymous operations cannot be captured | ||
// // using standard "graphql.query()" and "graphql.mutation()" handlers. | ||
// await waitFor(() => { | ||
// expect(consoleSpy.get('warning')).toEqual( | ||
// expect.arrayContaining([ | ||
// `[MSW] Failed to intercept a GraphQL request at "POST ${endpointUrl}": anonymous GraphQL operations are not supported. | ||
|
||
// Consider naming this operation or using "graphql.operation()" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/operation`, | ||
// ]), | ||
// ) | ||
// }) | ||
}) | ||
|
||
test('warns on handled anonymous GraphQL operation', async ({ | ||
loadExample, | ||
query, | ||
spyOnConsole, | ||
page, | ||
}) => { | ||
await loadExample(require.resolve('./anonymous-operation.mocks.ts')) | ||
const consoleSpy = spyOnConsole() | ||
|
||
await page.evaluate(() => { | ||
const { worker, graphql, HttpResponse } = window.msw | ||
|
||
worker.use( | ||
// This handler will have no effect on the anonymous operation performed. | ||
graphql.query('IrrelevantQuery', () => { | ||
return HttpResponse.json({ | ||
data: { | ||
user: { | ||
id: 'mocked-123', | ||
}, | ||
}, | ||
}) | ||
}), | ||
) | ||
}) | ||
|
||
const endpointUrl = httpServer.http.url('/graphql') | ||
const response = await query(endpointUrl, { | ||
query: gql` | ||
# Intentionally anonymous query. | ||
# It will be handled in the "graphql.operation()" handler above. | ||
query { | ||
user { | ||
id | ||
} | ||
} | ||
`, | ||
}) | ||
|
||
const json = await response.json() | ||
|
||
// Must get the original response because the "graphql.query()" | ||
// handler won't match an anonymous GraphQL operation. | ||
expect(json).toEqual({ | ||
data: { | ||
user: { | ||
id: 'abc-123', | ||
}, | ||
}, | ||
}) | ||
|
||
// Must print the warning because an anonymous operation has been performed. | ||
await waitFor(() => { | ||
expect(consoleSpy.get('warning')).toEqual( | ||
expect.arrayContaining([ | ||
`[MSW] Failed to intercept a GraphQL request at "POST ${endpointUrl}": anonymous GraphQL operations are not supported. | ||
Consider naming this operation or using "graphql.operation()" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/operation`, | ||
]), | ||
) | ||
}) | ||
}) | ||
|
||
test('does not print a warning on anonymous GraphQL operation handled by "graphql.operation()"', async ({ | ||
loadExample, | ||
spyOnConsole, | ||
page, | ||
query, | ||
}) => { | ||
await loadExample(require.resolve('./anonymous-operation.mocks.ts')) | ||
const consoleSpy = spyOnConsole() | ||
|
||
await page.evaluate(() => { | ||
const { worker, graphql, HttpResponse } = window.msw | ||
|
||
worker.use( | ||
// This handler will match ANY anonymous GraphQL operation. | ||
// It's a good idea to include some matching logic to differentiate | ||
// between those operations. We're omitting it for testing purposes. | ||
graphql.operation(() => { | ||
return HttpResponse.json({ | ||
data: { | ||
user: { | ||
id: 'mocked-123', | ||
}, | ||
}, | ||
}) | ||
}), | ||
) | ||
}) | ||
|
||
const endpointUrl = httpServer.http.url('/graphql') | ||
const response = await query(endpointUrl, { | ||
query: gql` | ||
# Intentionally anonymous query. | ||
# It will be handled in the "graphql.operation()" handler above. | ||
query { | ||
user { | ||
id | ||
} | ||
} | ||
`, | ||
}) | ||
|
||
const json = await response.json() | ||
|
||
// Must get the mocked response. | ||
expect(json).toEqual({ | ||
data: { | ||
user: { | ||
id: 'mocked-123', | ||
}, | ||
}, | ||
}) | ||
|
||
// Must not print any warnings because a permissive "graphql.operation()" | ||
// handler was used to capture and mock the anonymous GraphQL operation. | ||
expect(consoleSpy.get('warning')).toBeUndefined() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* @jest-environment node | ||
*/ | ||
import fetch from 'node-fetch' | ||
import { HttpServer } from '@open-draft/test-server/http' | ||
import { HttpResponse, graphql } from 'msw' | ||
import { setupServer } from 'msw/node' | ||
|
||
const httpServer = new HttpServer((app) => { | ||
app.post('/graphql', (req, res) => { | ||
res.json({ | ||
data: { | ||
user: { id: 'abc-123' }, | ||
}, | ||
}) | ||
}) | ||
}) | ||
|
||
const server = setupServer(graphql.query('GetUser', () => {})) | ||
|
||
beforeAll(async () => { | ||
server.listen() | ||
await httpServer.listen() | ||
jest.spyOn(console, 'warn').mockImplementation(() => {}) | ||
}) | ||
|
||
afterEach(() => { | ||
server.resetHandlers() | ||
jest.resetAllMocks() | ||
}) | ||
|
||
afterAll(async () => { | ||
jest.restoreAllMocks() | ||
server.close() | ||
await httpServer.close() | ||
}) | ||
|
||
test('warns on unhandled anonymous GraphQL operations', async () => { | ||
const endpointUrl = httpServer.http.url('/graphql') | ||
const response = await fetch(endpointUrl, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
query: ` | ||
query { | ||
user { | ||
id | ||
} | ||
} | ||
`, | ||
}), | ||
}) | ||
const json = await response.json() | ||
|
||
// Must receive the original server response. | ||
expect(json).toEqual({ | ||
data: { user: { id: 'abc-123' } }, | ||
}) | ||
|
||
// Must print a warning about the anonymous GraphQL operation. | ||
expect(console.warn).toHaveBeenCalledWith(`\ | ||
[MSW] Failed to intercept a GraphQL request at "POST ${endpointUrl}": anonymous GraphQL operations are not supported. | ||
Consider naming this operation or using "graphql.operation()" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/operation`) | ||
}) | ||
|
||
test('does not print a warning when using anonymous operation with "graphql.operation()"', async () => { | ||
server.use( | ||
graphql.operation(async ({ query, variables }) => { | ||
return HttpResponse.json({ | ||
data: { | ||
pets: [{ name: 'Tom' }, { name: 'Jerry' }], | ||
}, | ||
}) | ||
}), | ||
) | ||
|
||
const endpointUrl = httpServer.http.url('/graphql') | ||
const response = await fetch(endpointUrl, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
query: ` | ||
query { | ||
pets { | ||
name | ||
} | ||
} | ||
`, | ||
}), | ||
}) | ||
const json = await response.json() | ||
|
||
// Must get the mocked response. | ||
expect(json).toEqual({ | ||
data: { | ||
pets: [{ name: 'Tom' }, { name: 'Jerry' }], | ||
}, | ||
}) | ||
|
||
// Must print no warnings: operation is handled and doesn't | ||
// have to be named since we're using "graphql.operation()". | ||
expect(console.warn).not.toHaveBeenCalled() | ||
}) |