The Guild LogoThe Guild Monogram
Envelop Logo

Envelop

Get Started

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), }); }); });