# GraphQLDataFactory
Extends Helper
Helper for managing remote data using GraphQL queries. Uses data generators like rosie (opens new window) or factory girl to create new record.
By defining a factory you set the rules of how data is generated. This data will be saved on server via GraphQL queries and deleted in the end of a test.
# Use Case
Acceptance tests interact with a websites using UI and real browser. There is no way to create data for a specific test other than from user interface. That makes tests slow and fragile. Instead of testing a single feature you need to follow all creation/removal process.
This helper solves this problem. If a web application has GraphQL support, it can be used to create and delete test records. By combining GraphQL with Factories you can easily create records for tests:
I.mutateData('createUser', { name: 'davert', email: '[email protected]' });
let user = await I.mutateData('createUser', { name: 'davert'});
I.mutateMultiple('createPost', 3, {post_id: user.id});
To make this work you need
- GraphQL endpoint which allows to perform create / delete requests and
- define data generation rules
# Setup
Install Rosie (opens new window) and Faker (opens new window) libraries.
npm i rosie @faker-js/faker --save-dev
Create a factory file for a resource.
See the example for Users factories:
// tests/factories/users.js
const { Factory } = require('rosie').Factory;
const { faker } = require('@faker-js/faker');
// Used with a constructor function passed to Factory, so that the final build
// object matches the necessary pattern to be sent as the variables object.
module.exports = new Factory((buildObj) => ({
input: { ...buildObj },
}))
// 'attr'-id can be left out depending on the GraphQl resolvers
.attr('name', () => faker.name.findName())
.attr('email', () => faker.interact.email())
For more options see rosie documentation (opens new window).
Then configure GraphQLDataHelper to match factories and GraphQL schema:
# Configuration
GraphQLDataFactory has following config options:
endpoint
: URL for the GraphQL server.cleanup
(default: true): should inserted records be deleted up after testsfactories
: list of defined factoriesheaders
: list of headersGraphQL
: configuration for GraphQL requests.
See the example:
GraphQLDataFactory: {
endpoint: "http://user.com/graphql",
cleanup: true,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
factories: {
createUser: {
query: 'mutation createUser($input: UserInput!) { createUser(input: $input) { id name }}',
factory: './factories/users',
revert: (data) => ({
query: 'mutation deleteUser($id: ID!) { deleteUser(id: $id) }',
variables: { id : data.id},
}),
},
}
}
It is required to set GraphQL endpoint
which is the URL to which all the queries go to.
Factory file is expected to be passed via factory
option.
This Helper uses GraphQL (opens new window) helper and accepts its configuration in "GraphQL" section. For instance, to set timeout you should add:
"GraphQLDataFactory": {
"GraphQL": {
"timeout": "100000",
}
}
# Factory
Factory contains operations -
operation
: The operation/mutation that needs to be performed for creating a record in the backend.
Each operation must have the following:
query
: The mutation(query) string. It is expected to use variables to send data with the query.factory
: The path to factory file. The object built by the factory in this file will be passed as the 'variables' object to go along with the mutation.revert
: A function called with the data returned when an item is created. The object returned by this function is will be used to later delete the items created. So, make sure RELEVANT DATA IS RETURNED when a record is created by a mutation.
# Requests
Requests can be updated on the fly by using onRequest
function. For instance, you can pass in current session from a cookie.
onRequest: async (request) => {
// using global codeceptjs instance
let cookie = await codeceptjs.container.helpers('WebDriver').grabCookie('session');
request.headers = { Cookie: `session=${cookie.value}` };
}
# Responses
By default I.mutateData()
returns a promise with created data as specified in operation query string:
let client = await I.mutateData('createClient');
Data of created records are collected and used in the end of a test for the cleanup.
# Methods
# Parameters
config
# _requestCreate
Executes request to create a record to the GraphQL endpoint. Can be replaced from a custom helper.
# Parameters
operation
string (opens new window)variables
any to be sent along with the query
# _requestDelete
Executes request to delete a record to the GraphQL endpoint. Can be replaced from a custom helper.
# Parameters
operation
string (opens new window)data
any of the record to be deleted.
# mutateData
Generates a new record using factory, sends a GraphQL mutation to store it.
// create a user
I.mutateData('createUser');
// create user with defined email
// and receive it when inside async function
const user = await I.mutateData('createUser', { email: '[email protected]'});
# Parameters
operation
string (opens new window) to be performedparams
any predefined parameters
# mutateMultiple
Generates bunch of records and sends multiple GraphQL mutation requests to store them.
// create 3 users
I.mutateMultiple('createUser', 3);
// create 3 users of same age
I.mutateMultiple('createUser', 3, { age: 25 });
# Parameters
operation
string (opens new window)times
number (opens new window)params
any