Skip to content

Commit e5b67f2

Browse files
committed
chore: fix tests and add MSW license requestHandler file
1 parent 1e22429 commit e5b67f2

File tree

10 files changed

+63
-47
lines changed

10 files changed

+63
-47
lines changed

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pnpm-lock.yaml
2-
.storybook/public/mockServiceWorker.js
2+
.storybook/public/mockServiceWorker.js
3+
__generated__

.storybook/stories/ApolloClient.stories.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
ApolloApp,
55
ApolloAppWithDefer as AppWithDefer,
66
} from "./components/apollo-client/ApolloComponent.js";
7-
import { handler } from "../../src/__tests__/mocks/handlers.js";
7+
import { graphQLHandler } from "../../src/__tests__/mocks/handlers.js";
88

99
export default {
1010
title: "Example/Apollo Client",
@@ -13,7 +13,7 @@ export default {
1313
layout: "centered",
1414
msw: {
1515
handlers: {
16-
graphql: handler,
16+
graphql: graphQLHandler,
1717
},
1818
},
1919
},

.storybook/stories/Relay.stories.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
RelayApp,
55
RelayAppWithDefer as AppWithDefer,
66
} from "./components/relay/RelayComponent.js";
7-
import { handler } from "../../src/__tests__/mocks/handlers.js";
7+
import { graphQLHandler } from "../../src/__tests__/mocks/handlers.js";
88

99
export default {
1010
title: "Example/Relay",
@@ -13,7 +13,7 @@ export default {
1313
layout: "centered",
1414
msw: {
1515
handlers: {
16-
graphql: handler,
16+
graphql: graphQLHandler,
1717
},
1818
},
1919
},

jest.config.cjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ module.exports = {
1818
testEnvironmentOptions: {
1919
customExportConditions: [""],
2020
},
21-
collectCoverageFrom: ["src/**/*.ts", "!src/__tests__/**/*.ts"],
21+
collectCoverageFrom: [
22+
"src/**/*.ts",
23+
"!src/__tests__/**/*.ts",
24+
"!src/requestHandler.ts",
25+
],
2226
coverageReporters: ["html", "json-summary", "text", "text-summary"],
2327
reporters: ["default", ["jest-junit", { outputDirectory: "coverage" }]],
2428
transform: {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@
126126
"@graphql-tools/utils": "^10.3.2",
127127
"@types/statuses": "^2.0.5",
128128
"graphql-tag": "^2.12.6",
129-
"is-node-process": "^1.2.0"
129+
"is-node-process": "^1.2.0",
130+
"outvariant": "^1.4.3"
130131
},
131132
"peerDependencies": {
132133
"graphql": "^15.0.0 || ^16.0.0",

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__tests__/handlers.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,13 @@ describe("integration tests with github schema", () => {
180180
githubTypeDefs,
181181
{
182182
IssueConnection: {
183+
// @ts-expect-error need better TS-fu to accept a deep partial of
184+
// whatever the resolver type returns here
183185
edges: (_parent, _args, _context, info) => {
184186
return Array(parseInt(info.variableValues.last as string))
185187
.fill(null)
186188
.map((_item, idx) => ({
187-
// cursor: "2",
189+
cursor: "2",
188190
node: {
189191
title: `Some issue ${idx}`,
190192
url: `https://github.com/foo-bar/issues/${idx}`,
@@ -232,10 +234,8 @@ describe("integration tests with github schema", () => {
232234
variables: { owner: "octocat", name: "Hello World", last: "5" },
233235
});
234236

235-
if (data) {
236-
// console.log(data.repository.issues.edges);
237-
}
238237
if (!data) return null;
238+
239239
return (
240240
<ul>
241241
{data.repository.issues.edges.map((item) => (

src/handlers.ts

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
11
import { gql } from "graphql-tag";
22
import { execute } from "@graphql-tools/executor";
33
import { isNodeProcess } from "is-node-process";
4-
import {
5-
type ExecutionResult,
6-
type GraphQLSchema,
7-
type DocumentNode,
8-
} from "graphql";
9-
import {
10-
HttpResponse,
11-
graphql,
12-
delay as mswDelay,
13-
type GraphQLQuery,
14-
type GraphQLVariables,
15-
type ResponseResolver,
16-
} from "msw";
4+
import type { GraphQLSchema, DocumentNode } from "graphql";
5+
import { HttpResponse, delay as mswDelay, type ResponseResolver } from "msw";
176
import type {
187
InitialIncrementalExecutionResult,
198
SingularExecutionResult,
@@ -53,9 +42,7 @@ type DocumentResolversWithOptions<TResolvers> = {
5342
mocks?: IMocks<TResolvers>;
5443
} & DelayOptions;
5544

56-
type Resolvers<TResolvers> =
57-
| Partial<TResolvers>
58-
| ((store: IMockStore) => Partial<TResolvers>);
45+
type Resolvers<TResolvers> = TResolvers | ((store: IMockStore) => TResolvers);
5946

6047
type SchemaWithOptions<TResolvers> = {
6148
schema: GraphQLSchema;
@@ -81,9 +68,7 @@ function createHandler<TResolvers>(
8168

8269
function createSchemaWithDefaultMocks<TResolvers>(
8370
typeDefs: DocumentNode,
84-
resolvers?:
85-
| Partial<TResolvers>
86-
| ((store: IMockStore) => Partial<TResolvers>),
71+
resolvers?: TResolvers | ((store: IMockStore) => TResolvers),
8772
mocks?: IMocks<TResolvers>,
8873
) {
8974
const executableSchema = makeExecutableSchema({ typeDefs });
@@ -104,7 +89,7 @@ function createSchemaWithDefaultMocks<TResolvers>(
10489
(resolvers ?? {}) as Maybe<
10590
IResolvers<{ __typename?: string | undefined }, unknown>
10691
>,
107-
]) as Partial<TResolvers>,
92+
]) as TResolvers,
10893
preserveResolvers: true,
10994
});
11095
}
@@ -207,9 +192,7 @@ function createHandlerFromSchema<TResolvers>(
207192
const requestHandler = createCustomRequestHandler();
208193

209194
return Object.assign(
210-
requestHandler<
211-
ExecutionResult<Record<string, unknown>, Record<string, unknown>>
212-
>(async ({ query, variables, operationName }) => {
195+
requestHandler(async ({ query, variables, operationName }) => {
213196
const document = gql(query as string);
214197
const hasDeferOrStream = hasDirectives(["defer", "stream"], document);
215198

@@ -291,12 +274,8 @@ function createHandlerFromSchema<TResolvers>(
291274
}
292275

293276
const createCustomRequestHandler = () => {
294-
return <
295-
Query extends GraphQLQuery = GraphQLQuery,
296-
Variables extends GraphQLVariables = GraphQLVariables,
297-
>(
298-
resolver: ResponseResolver,
299-
) => new CustomRequestHandler("all", new RegExp(".*"), "*", resolver);
277+
return (resolver: ResponseResolver) =>
278+
new CustomRequestHandler("all", new RegExp(".*"), "*", resolver);
300279
};
301280

302281
export { createHandler, createHandlerFromSchema, createSchemaWithDefaultMocks };

src/requestHandler.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import statuses from "@bundled-es-modules/statuses";
2+
import { format } from "outvariant";
23

34
import {
45
GraphQLHandler,
@@ -7,6 +8,21 @@ import {
78
type ParsedGraphQLRequest,
89
} from "msw";
910

11+
// These utilities are taken wholesale from MSW, as they're not exported from
12+
// the package, in order to build an augmented version of MSW's
13+
// graphql.operation catchall request handler class.
14+
15+
// MIT License
16+
17+
// Copyright (c) 2018–present Artem Zakharchenko
18+
19+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
20+
21+
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
22+
23+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
25+
// From https://github.com/mswjs/msw/blob/63b78315cdbe8435f9e6ec627022d67fa38a9703/src/core/handlers/GraphQLHandler.ts#L35
1026
export type GraphQLRequestParsedResult = {
1127
match: Match;
1228
cookies: Record<string, string>;
@@ -107,13 +123,26 @@ export function getStatusCodeColor(status: number): StatusCodeColor {
107123
return StatusCodeColor.Danger;
108124
}
109125

126+
const LIBRARY_PREFIX = "[MSW]";
127+
128+
/**
129+
* Formats a given message by appending the library's prefix string.
130+
*/
131+
function formatMessage(message: string, ...positionals: any[]): string {
132+
const interpolatedMessage = format(message, ...positionals);
133+
return `${LIBRARY_PREFIX} ${interpolatedMessage}`;
134+
}
135+
136+
const devUtils = {
137+
formatMessage,
138+
};
139+
110140
export class CustomRequestHandler extends GraphQLHandler {
111141
override async log(args: {
112142
request: Request;
113143
response: Response;
114144
parsedResult: GraphQLRequestParsedResult;
115145
}) {
116-
// can expose some methods for digging into the mock schema?
117146
const loggedRequest = await serializeRequest(args.request);
118147
const loggedResponse = await serializeResponse(args.response);
119148
const statusColor = getStatusCodeColor(loggedResponse.status);
@@ -122,9 +151,11 @@ export class CustomRequestHandler extends GraphQLHandler {
122151
: `anonymous ${args.parsedResult.operationType}`;
123152

124153
console.groupCollapsed(
125-
`${getTimestamp()} ${requestInfo} (%c${loggedResponse.status} ${
126-
loggedResponse.statusText
127-
}%c)`,
154+
devUtils.formatMessage(
155+
`${getTimestamp()} ${requestInfo} (%c${loggedResponse.status} ${
156+
loggedResponse.statusText
157+
}%c)`,
158+
),
128159
`color:${statusColor}`,
129160
"color:inherit",
130161
);

src/utilities.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ import {
88
isScalarType,
99
visit,
1010
BREAK,
11-
GraphQLScalarType,
12-
Kind,
13-
GraphQLError,
1411
} from "graphql";
1512

1613
function hasDirectives(names: string[], root: ASTNode, all?: boolean) {

0 commit comments

Comments
 (0)