UNPKG

@binpar/jest-gql

Version:

GraphQL based tests for Jest

214 lines (168 loc) 6.36 kB
# GraphQL based tests for Jest [![Build Status](https://travis-ci.org/BinPar/jest-gql.svg?branch=master)](https://travis-ci.org/BinPar/jest-gql) [![Coverage Status](https://coveralls.io/repos/github/BinPar/jest-gql/badge.svg?branch=master)](https://coveralls.io/github/BinPar/jest-gql?branch=master) **jest-gql** is a minimalistic framework for GraphQL tests using jest and Apollo Client - [How to use](#how-to-use) - [Setup](#setup) - [Creating the tests](#creating-the-tests) - [Composed test example](#composed-test-example) - [Oauth token authentication](#oauth-token-authentication) - [Remarks](#remarks) - [Executing the tests](#executing-the-tests) ## How to use ### Setup ```bash npm install --save-dev @binpar/jest-gql react react-apollo react-dom graphql-tag jest apollo-client ``` > If you are using ```"jest": "^21.2.1"``` please update to ```"jest": "^22.2.2"``` an error with the 21.1.1 version in the async test system makes it incompatible with **jest-gql**. If you have need to setup babel and eslint we recommend to add this packages too (otherwise jump to [executing the tests](#executing-the-tests): ```bash npm install --save-dev babel-cli babel-core babel-loader babel-plugin-inline-import babel-plugin-transform-exponentiation-operator babel-plugin-transform-object-rest-spread babel-preset-env babel-preset-es2015 babel-register eslint eslint-plugin-import eslint-plugin-jsx-a11y ``` And create the **.babelrc** and **.eslintrc** in the application directory: #### .babelrc ```json { "presets": [ [ "env", { "targets": { "node": "6.11" } } ] ], "plugins": [ [ "transform-object-rest-spread", { "useBuiltIns": true } ], [ "babel-plugin-inline-import", { "extensions": [".json", ".gql", ".graphql"] } ], "transform-exponentiation-operator" ] } ``` #### .eslintrc ```json { "extends": [ "airbnb" ], "rules": { "no-underscore-dangle": [ "error", { "allow": [ "_id" ] } ], "import/no-extraneous-dependencies": 0 } } ``` ### Creating the tests It is recommended to create a **folder** in the root of the project called ```test``` and a ```__tests__``` folder inside it. On the ```__tests__``` folder we will place the tests that will be executed by the framework. On the ```test``` folder we will place the tests that are going to be required as pre-requisites by our tests (like a login GraphQL mutation used in several tests but not executed by it shelf). As an example, by adding a file called ```allWorks.js``` to the tests ```__tests__``` folder we will setup a test: ```javascript import gql from 'graphql-tag'; import runGQLTest from '@binpar/jest-gql'; const test = { name: 'Get Works List', gql: gql` query ($catalogPrefix: String!){ getWorks(catalogPrefix:$catalogPrefix, limit:20) { id title } } `, vars: () => ({ catalogPrefix: 'AM18' }), result: res => ({ workId: res.getWorks[0].id }), test: data => !!data.workId, repeat: 2, endPoint: process.env.GQL_API_URL, }; runGQLTest(test); export default test; ``` The properties of the tests are: **previous**: Array with the reference of the tests that need to be executed before the current test (typically stored in the parent folder). **name**: The name of the test **gql**: The gql request to execute **vars**: The variables that we will used by the gql. The function will receive a data object containing the data of the previous tests (all the tests setup in the previous property) **result**: A function that will be executed after the GraphQL execution that will allow us to setup what information do we retrieve from the server response. **test**: A function that will be executed with the data generated by the result (and the previous test) and will return a **boolean** indicating the test result (**true**: success, **false**: fail). **endPoint**: URL of the GraphQL end point. **repeat**: The number of times that we want the test to be runned ### Composed test example ```test/login.js```: ```javascript import gql from 'graphql-tag'; const test = { name: 'Login Test', gql: gql` mutation($email: String!, $password: String!) { login(email: $email, password: $password) { error token } } `, vars: () => ({ email: 'voceses@email.com', password: 'voceses' }), result: data => ({ error: data.login.error, oAuthToken: data.login.token }), test: data => !data.error, }; export default test; ``` ```test/__tests__/me.js```: ```javascript import gql from 'graphql-tag'; import runGQLTest from '@binpar/jest-gql'; import login from '../login'; const test = { previous: [login], name: 'Query authenticated user data', gql: gql` query { me { id name email } } `, result: data => ({ userEmail: data.me.email }), test: data => data.userEmail === 'voceses@email.com', endPoint: process.env.GQL_API_URL, }; runGQLTest(test); export default test; ``` Notice that the test that will run is ```me.js```, but it will execute ```login.js``` as a pre-requisite that will be shared by many tests. ### Oauth token authentication In the previous example, in the ```login.js``` the token returned by the query is stored in the data in the **oAuthToken** property. This is a special property that will be used for the subsequent requests of this test in order to authenticate the user using **Oauth token authentication**. ### Remarks All the tests stored in ```__tests__``` will run in parallel, but the execution plan of one test (resulting of the recursive evaluation of the **previous** property will be executed in serial). Every test will use an unique ApolloClient and NetworkInterface during the execution. ### Executing the tests It is recommended to add this two lines to the **scripts** section of the **package.json**: ```json { "scripts": { "test": "GQL_API_URL='[your endpoint URL]' jest", "testDev": "GQL_API_URL='[your endpoint URL]' jest --watch" } } ``` The first one will allow us to use **npm run test** to run all the tests. The second one will allow us to use **npm run testDev** to execute the tests in interactive mode during the development.