@envelop/testing
Version:
181 lines (180 loc) • 6.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.collectAsyncIteratorValues = exports.assertStreamExecutionValue = exports.assertSingleExecutionValue = exports.createTestkit = exports.createSpiedPlugin = void 0;
const graphql_1 = require("graphql");
const core_1 = require("@envelop/core");
const utils_1 = require("@graphql-tools/utils");
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function createSpiedPlugin() {
const afterResolver = jest.fn();
const baseSpies = {
onSchemaChange: jest.fn(),
afterParse: jest.fn(),
afterValidate: jest.fn(),
afterContextBuilding: jest.fn(),
afterExecute: jest.fn(),
afterResolver,
beforeResolver: jest.fn(() => afterResolver),
};
const spies = {
...baseSpies,
beforeParse: jest.fn(() => baseSpies.afterParse),
beforeValidate: jest.fn(() => baseSpies.afterValidate),
beforeContextBuilding: jest.fn(() => baseSpies.afterContextBuilding),
beforeExecute: jest.fn(() => ({
onExecuteDone: baseSpies.afterExecute,
})),
};
return {
reset: () => {
for (const [, value] of Object.entries(spies)) {
value.mockReset();
}
},
spies,
plugin: {
onSchemaChange: spies.onSchemaChange,
onParse: spies.beforeParse,
onValidate: spies.beforeValidate,
onExecute: spies.beforeExecute,
onContextBuilding: spies.beforeContextBuilding,
},
};
}
exports.createSpiedPlugin = createSpiedPlugin;
function createTestkit(pluginsOrEnvelop, schema) {
const toGraphQLErrorOrThrow = (thrownThing) => {
if (thrownThing instanceof graphql_1.GraphQLError) {
return thrownThing;
}
throw thrownThing;
};
const phasesReplacements = [];
let getEnveloped = Array.isArray(pluginsOrEnvelop)
? (0, core_1.envelop)({
plugins: [...(schema ? [(0, core_1.useSchema)((0, utils_1.mapSchema)(schema))] : []), ...pluginsOrEnvelop],
parse: graphql_1.parse,
execute: graphql_1.execute,
validate: graphql_1.validate,
subscribe: graphql_1.subscribe,
})
: pluginsOrEnvelop;
return {
modifyPlugins(modifyPluginsFn) {
getEnveloped = (0, core_1.envelop)({
plugins: [...(schema ? [(0, core_1.useSchema)((0, utils_1.mapSchema)(schema))] : []), ...modifyPluginsFn(getEnveloped._plugins)],
parse: graphql_1.parse,
execute: graphql_1.execute,
validate: graphql_1.validate,
subscribe: graphql_1.subscribe,
});
},
mockPhase(phaseReplacement) {
phasesReplacements.push(phaseReplacement);
},
wait: ms => new Promise(resolve => setTimeout(resolve, ms)),
execute: async (operation, variableValues = {}, initialContext = {}) => {
const proxy = getEnveloped(initialContext);
for (const replacement of phasesReplacements) {
switch (replacement.phase) {
case 'parse':
proxy.parse = replacement.fn;
break;
case 'validate':
proxy.validate = replacement.fn;
break;
case 'subscribe':
proxy.subscribe = replacement.fn;
break;
case 'execute':
proxy.execute = replacement.fn;
break;
case 'contextFactory':
proxy.contextFactory = replacement.fn;
break;
}
}
let document;
try {
document = (0, utils_1.isDocumentNode)(operation) ? operation : proxy.parse(operation);
}
catch (err) {
return {
errors: [toGraphQLErrorOrThrow(err)],
};
}
let validationErrors;
try {
validationErrors = proxy.validate(proxy.schema, document);
}
catch (err) {
return {
errors: [toGraphQLErrorOrThrow(err)],
};
}
if (validationErrors.length > 0) {
return {
errors: validationErrors,
};
}
const mainOperation = (0, graphql_1.getOperationAST)(document);
if (mainOperation == null) {
return {
errors: [new graphql_1.GraphQLError('Could not identify main operation.')],
};
}
const contextValue = await proxy.contextFactory({
request: {
headers: {},
method: 'POST',
query: '',
body: {
query: (0, graphql_1.print)(document),
variables: variableValues,
},
},
document,
operation: (0, graphql_1.print)(document),
variables: variableValues,
...initialContext,
});
if (mainOperation.operation === 'subscription') {
return proxy.subscribe({
variableValues,
contextValue,
schema: proxy.schema,
document,
rootValue: {},
});
}
return proxy.execute({
variableValues,
contextValue,
schema: proxy.schema,
document,
rootValue: {},
});
},
};
}
exports.createTestkit = createTestkit;
function assertSingleExecutionValue(input) {
if ((0, core_1.isAsyncIterable)(input)) {
throw new Error('Received stream but expected single result');
}
}
exports.assertSingleExecutionValue = assertSingleExecutionValue;
function assertStreamExecutionValue(input) {
if (!(0, core_1.isAsyncIterable)(input)) {
throw new Error('Received single result but expected stream.');
}
}
exports.assertStreamExecutionValue = assertStreamExecutionValue;
const collectAsyncIteratorValues = async (asyncIterable) => {
const values = [];
for await (const value of asyncIterable) {
values.push(value);
}
return values;
};
exports.collectAsyncIteratorValues = collectAsyncIteratorValues;