1.0.0-alpha.19 • Published 3 years ago

graphql-sonar v1.0.0-alpha.19

Weekly downloads
-
License
MIT
Repository
-
Last release
3 years ago

GraphQL Sonar

An API testing tool for GraphQL, leveraging code generation based on your schema and operations

The Motivation

When you want to make sure your services are working in production as intended, beyond the scope of your testing infrastructure based on unit and integration tests, you may want to send real queries and mutations against your production deployments, as this is the only way to assert that everything is really working for your users and customers.

While uptime testing tools are great for static queries, with GraphQL, we can leverage the queries we already use for our frontend applications, or write them ourselves to generate everything we need to create robust end-to-end tests that run wherever we need them, whether that is after every deployment or scheduled every day or night, your team is complete in charge of that.

GraphQL Sonar aims to be the connection between your operations and end-to-end tests running against real deployments. As this involves the network layer and all external services you may be using, GraphQL Sonar should only be used for the most important parts, for example sign up and onboarding, auth in general, billing and checkout, and other critical or hot paths.

Focusing on these will give you certainty that your systems are really working, while running as fast as possible, making them suitable to run whenever you wish. For every other case, check out the talk on Testing GraphQL APIs, which goes through different ways you can test your backend services exposing GraphQL APIs.

GraphQL Sonar will get you started writing and running end-to-end GraphQL tests quickly, but will never impose any restrictions on how you want to test: While we export a simple test runner for getting started, using the generated operations in an external framework such as Jest is not at all discouraged.

Getting started

Installing graphql-sonar

yarn install graphql-sonar

Creating or locating your operations

You might already have operations defined when you query your GraphQL API in a frontend application. Usually all queries or mutations are placed in separate .graphql files, which graphql-sonar supports right out of the box. If you're not using the same operations, or if there are none to begin with, you can create some queries right now.

Generating testing code

After creating your operations, graphql-sonar will use the latest schema of your API to validate the operations and generate both type definitions and helper functions for testing in TypeScript.

Every defined operation will lead to a generated function performing a request against a configured endpoint and returning the GraphQL result, as well as some additional data.

graphql-sonar \
    --schema [file path or URL to your API endpoint] \
    --operations [path or glob to your operation file(s)] \
    --output [optional path where to store the generated output, defaults to sonar.ts]

Writing tests with the built-in reporter

Now that you generated some types, let's get to writing and running tests!

GraphQL Sonar exports a couple of convenience methods for running simple test cases. Whenever you need more flexibility, you can invoke all generated functions on your own and use existing testing frameworks like Jest, or build your own.

// Import some general-purpose Sonar structures
import { runOperations, SonarConfig } from "graphql-sonar";

// Import our generated operations
import { createUser, fetchUser } from "./sonar";

const config: SonarConfig = {
  // Our live endpoint we want to query
  endpoint: "<Your API Endpoint>",

  // Optionally pass an access token if we want to
  // perform restricted operations
  headers: {
    Authorization: `Bearer ${process.env.AUTH_TOKEN}`,
  },
};

// Temporarily store our user's ID
let createdUserId: string | undefined;

// Run all operations one-by-one, and fail early
runOperations([
  // Start by creating user with mutation
  async () => {
    const res = await createUser(config, {
      data: {
        name: "Sonar Sample User",
      },
    });

    createdUserId = res.graphql.data?.createUser.id;

    return res;
  },
  // Continue to fetch user with query
  () => {
    if (!createdUserId) {
      throw new Error("Missing user ID");
    }
    return fetchUser(config, {
      data: { id: createdUserId },
    });
  },
]);

Automating test runs

With GraphQL Sonar, you're free to choose where and when to run your end-to-end tests. You could run them whenever a new deployment is made, on a fixed schedule, or just manually when you want to make sure everything's working. You can potentially run Sonar in every CI system, and other environments alike.

GitHub Actions Example Workflow

name: Run Sonar Tests
on:
  # Allow to run tests manually
  workflow_dispatch:
  # Run tests every night
  schedule:
    - cron: "0 0 * * *"
  # Run tests when pushing to main
  push:
    paths:
      # Rerun the tests when we change this workflow
      # Has to match your workflow file location
      - ".github/workflows/sonar.yaml"

      # Rerun the tests when they change
      - "tests"
    branches:
      - main
jobs:
  run-sonar:
    name: Run Sonar tests
    runs-on: ubuntu-20.04
    steps:
      # Check out latest code
      - name: Checkout
        uses: actions/checkout@v2
      # Configure this step to match your environment
      # Here you can install tools, build your code and run the tests
      - name: Run tests
        run: |
          yarn install          
          yarn build
          node tests/index.js

Examples

Contributing

If you