forked from keystonejs/keystone
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
@keystone-next/testing example (keystonejs#5887)
- Loading branch information
Showing
13 changed files
with
1,227 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# @keystone-next/example-testing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
## Feature Example - Testing | ||
|
||
This project demonstrates how to write tests against the GraphQL API to your Keystone system. | ||
It builds on the [`withAuth()`](../with-auth) example project. | ||
|
||
## Instructions | ||
|
||
To run this project, clone the Keystone repository locally then navigate to this directory and run: | ||
|
||
```shell | ||
yarn dev | ||
``` | ||
|
||
This will start the Admin UI at [localhost:3000](http://localhost:3000). | ||
You can use the Admin UI to create items in your database. | ||
|
||
You can also access a GraphQL Playground at [localhost:3000/api/graphql](http://localhost:3000/api/graphql), which allows you to directly run GraphQL queries and mutations. | ||
|
||
## Features | ||
|
||
Keystone provides a testing library in the package [`@keystone-next/testing`](https://next.keystonejs.com/guides/testing) which helps you write tests using [Jest](https://jestjs.io/). | ||
This example project uses this library to add tests to the [`withAuth()`](../with-auth) example project. The tests can be found in [example.test.ts](./example.test.ts) | ||
|
||
### Test runner | ||
|
||
The function `setupTestRunner` takes the project's `KeystoneConfig` object and creates a `runner` function. This test runner is then used to wrap a test function. | ||
|
||
```typescript | ||
import { setupTestRunner } from '@keystone-next/testing'; | ||
import config from './keystone'; | ||
|
||
const runner = setupTestRunner({ config }); | ||
|
||
describe('Example tests using test runner', () => { | ||
test( | ||
'Create a Person using the list items API', | ||
runner(async ({ context }) => { | ||
... | ||
}) | ||
); | ||
}); | ||
``` | ||
|
||
For each test, the runner will connect to the database and drop all the data so that the test can run in a known state, and also handle disconnecting from the database after the test. | ||
|
||
#### `context` | ||
|
||
The test runner provides the test function with a [`KeystoneContext`](https://next.keystonejs.com/apis/context) argument called `context`. This is the main API for interacting with the Keystone system. It can be used to read and write data to the system and verify that the system is behaving as expected. | ||
|
||
```typescript | ||
test( | ||
'Create a Person using the list items API', | ||
runner(async ({ context }) => { | ||
const person = await context.lists.Person.createOne({ | ||
data: { name: 'Alice', email: '[email protected]', password: 'super-secret' }, | ||
query: 'id name email password { isSet }', | ||
}); | ||
expect(person.name).toEqual('Alice'); | ||
expect(person.email).toEqual('[email protected]'); | ||
expect(person.password.isSet).toEqual(true); | ||
}) | ||
); | ||
``` | ||
|
||
#### `graphQLRequest` | ||
|
||
The test runner also provides the function with an argument `graphQLRequest`, which is a [`supertest`](https://github.com/visionmedia/supertest) request configured to accept arguments `{ query, variable, operation }` and send them to your GraphQL API. You can use the `supertest` API to set additional request headers and to check that the response returned is what you expected. | ||
|
||
```typescript | ||
test( | ||
'Create a Person using a hand-crafted GraphQL query sent over HTTP', | ||
runner(async ({ graphQLRequest }) => { | ||
const { body } = await graphQLRequest({ | ||
query: `mutation { | ||
createPerson(data: { name: "Alice", email: "[email protected]", password: "super-secret" }) { | ||
id name email password { isSet } | ||
} | ||
}`, | ||
}).expect(200); | ||
const person = body.data.createPerson; | ||
expect(person.name).toEqual('Alice'); | ||
expect(person.email).toEqual('[email protected]'); | ||
expect(person.password.isSet).toEqual(true); | ||
}) | ||
); | ||
``` | ||
|
||
### Test environment | ||
|
||
The function `setupTestEnv` is used to set up a test environment which can be used across multiple tests. | ||
|
||
```typescript | ||
import { KeystoneContext } from '@keystone-next/types'; | ||
import { setupTestEnv, TestEnv } from '@keystone-next/testing'; | ||
import config from './keystone'; | ||
|
||
describe('Example tests using test environment', () => { | ||
let testEnv: TestEnv, context: KeystoneContext; | ||
beforeAll(async () => { | ||
testEnv = await setupTestEnv({ config }); | ||
context = testEnv.testArgs.context; | ||
|
||
await testEnv.connect(); | ||
|
||
// Perform any setup such as data seeding here. | ||
}); | ||
afterAll(async () => { | ||
await testEnv.disconnect(); | ||
}); | ||
|
||
test('Check that the persons password is set', async () => { | ||
... | ||
}); | ||
}); | ||
``` | ||
|
||
`setupTestEnv` will connect to the database and drop all the data so that the test can run in a known state, returning a value `testEnv` which contains `{ connect, disconnect, testArgs }`. | ||
The value `testArgs` contains the same values that are passed into test functions by the test runner. | ||
The `connect` and `disconnect` functions are used to connect to the database before the tests run, then disconnect once all tests have completed. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
module.exports = { | ||
presets: [ | ||
[ | ||
'@babel/preset-env', | ||
{ | ||
targets: { | ||
node: 10, | ||
browsers: [ | ||
'last 2 chrome versions', | ||
'last 2 firefox versions', | ||
'last 2 safari versions', | ||
'last 2 edge versions', | ||
], | ||
}, | ||
}, | ||
], | ||
'@babel/preset-react', | ||
'@babel/preset-typescript', | ||
], | ||
plugins: [ | ||
'@babel/plugin-transform-runtime', | ||
'@babel/plugin-proposal-class-properties', | ||
'@babel/proposal-object-rest-spread', | ||
'@babel/plugin-syntax-dynamic-import', | ||
], | ||
overrides: [ | ||
{ | ||
include: 'packages/fields/src/Controller.js', | ||
presets: ['@babel/preset-env'], | ||
}, | ||
], | ||
}; |
Oops, something went wrong.