Testing#
Envelop comes with a dedicated package for testing purposes. You can use it to test your plugin or your whole envelop, by replacing or mocking other plugins / phases.
The Envelop testkit can also help you to test your envelop plugins in a headless envrionment, so you don't need to deal with HTTP or anything else.
To get stated with the Envelop testkit, make sure to install it in your project (as a devDependency
):
yarn add -D @envelop/testing
To get started with your envelop
testing, make sure first to setup your favorite test runner in your project (we use Jest).
Testing a plugin#
To test a plugin in a real GraphQL environment, just create a testkit envelop:
import { useMyPlugin } from './my-plugin';
import { createTestkit, assertSingleExecutionValue } from '@envelop/testing';
describe('My Plugin', () => {
const mySchema = buildSchema(`type Query { foo: String }`);
it('Should run correctly with no errors', async () => {
// Create a testkit for the plugin, using the plugin and a dummy schema
const testkit = createTestkit([useMyPlugin], mySchema);
// Execute the envelop using a simple query
const result = await testkit.execute(`query testQuery { foo }`);
// During tests, it's simpler to assume you are dealing with a non-stream responses
assertSingleExecutionValue(result);
// Assert that the result is correct
expect(result.data).toBeDefined();
});
});
Testing Envelop instance#
You can also pass a complete instance of envelop
(the getEnveloped
function) to your testkit, and run the same testing flow for multiple plugins together:
import { getEnveloped } from './my-app';
import { createTestkit, assertSingleExecutionValue } from '@envelop/testing';
describe('My GQL App', () => {
const mySchema = buildSchema(`type Query { foo: String }`);
it('Should run correctly with no errors', async () => {
// Create a testkit based on the envelop, with a dummy schema
const testkit = createTestkit(getEnveloped, mySchema);
// Execute the envelop using a simple query
const result = await testkit.execute(`query testQuery { foo }`);
// During tests, it's simpler to assume you are dealing with a non-stream responses
assertSingleExecutionValue(result);
// Assert that the result is correct
expect(result.data).toBeDefined();
});
});
Additional Resources#
Manipulating Envelops#
If you are testing a complete envelop
, you might want to manipulate the envelop before executing it (for example, to replace a context function that authenticate the user, or to create a scenario needed for testing).
You can use modifyPlugins
in order to modify the plugins that are part of your execution:
// Create a testkit based on the envelop, with a dummy schema
const testkit = createTestkit(getEnveloped, mySchema);
// Modify the envelop's plugins
testkit.modifyPlugins(plugins => [...plugins, somePlugins]);
// Execute the envelop using a simple query
const result = await testkit.execute(`query testQuery { foo }`);
You can either add plugins, but also replace/remove plugins that are not needed during testing.
Mocking Phases#
If you need to make sure that a specific phase of envelop
will perform a specific result, you can replace the entire phase with a custom one.
This is useful if you need to prepare with a specific scenario before running your envelop, without the need to deal with specific plugins.
Here's an example for replacing the whole context building phase:
// Create a testkit based on the envelop, with a dummy schema
const testkit = createTestkit(getEnveloped, mySchema);
// Replace the entire context factory phase
testkit.mockPhase({
phase: 'contextFactory',
fn: () => ({
currentUser: {
id: 1,
},
}),
});
Note: Replacing whole phases might effect plugins execution, so use it carefully!
Spying On Phases#
If you are using Jest, you can use a pre-defined plugin that can help you spy on Envelop phases and check the validity of your parameters.
import { getEnveloped } from './my-app';
import { createTestkit, assertSingleExecutionValue } from '@envelop/testing';
describe('My GQL App', () => {
const mySchema = buildSchema(`type Query { foo: String }`);
it('Should run correctly with no errors', async () => {
const spy = createSpiedPlugin();
const testkit = createTestkit(getEnveloped, mySchema);
testkit.modifyPlugins(plugins => [...plugins, spy.plugin]);
const result = await testkit.execute(`query testQuery { foo }`);
assertSingleExecutionValue(result);
// Assert and test
expect(spy.spies.beforeContextBuilding).toHaveBeenCalledWith({
context: expect.objectContaining({
test: true,
}),
extendContext: expect.any(Function),
});
});
});